Initial revision
authorokuji <okuji@localhost>
Fri, 27 Dec 2002 08:53:07 +0000 (08:53 +0000)
committerokuji <okuji@localhost>
Fri, 27 Dec 2002 08:53:07 +0000 (08:53 +0000)
80 files changed:
.cvsignore [new file with mode: 0644]
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile.in [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
THANKS [new file with mode: 0644]
TODO [new file with mode: 0644]
aclocal.m4 [new file with mode: 0644]
autogen.sh [new file with mode: 0644]
boot/i386/pc/boot.S [new file with mode: 0644]
boot/i386/pc/diskboot.S [new file with mode: 0644]
conf/i386-pc.mk [new file with mode: 0644]
conf/i386-pc.rmk [new file with mode: 0644]
config.guess [new file with mode: 0644]
config.h.in [new file with mode: 0644]
config.sub [new file with mode: 0644]
configure [new file with mode: 0644]
configure.ac [new file with mode: 0644]
disk/i386/pc/biosdisk.c [new file with mode: 0644]
disk/i386/pc/partition.c [new file with mode: 0644]
fs/fat.c [new file with mode: 0644]
genkernsyms.sh [new file with mode: 0644]
genmk.rb [new file with mode: 0644]
genmodsrc.sh [new file with mode: 0644]
gensymlist.sh [new file with mode: 0644]
include/grub/boot.h [new file with mode: 0644]
include/grub/device.h [new file with mode: 0644]
include/grub/disk.h [new file with mode: 0644]
include/grub/dl.h [new file with mode: 0644]
include/grub/elf.h [new file with mode: 0644]
include/grub/err.h [new file with mode: 0644]
include/grub/file.h [new file with mode: 0644]
include/grub/fs.h [new file with mode: 0644]
include/grub/i386/pc/biosdisk.h [new file with mode: 0644]
include/grub/i386/pc/boot.h [new file with mode: 0644]
include/grub/i386/pc/console.h [new file with mode: 0644]
include/grub/i386/pc/init.h [new file with mode: 0644]
include/grub/i386/pc/kernel.h [new file with mode: 0644]
include/grub/i386/pc/loader.h [new file with mode: 0644]
include/grub/i386/pc/memory.h [new file with mode: 0644]
include/grub/i386/pc/partition.h [new file with mode: 0644]
include/grub/i386/types.h [new file with mode: 0644]
include/grub/kernel.h [new file with mode: 0644]
include/grub/loader.h [new file with mode: 0644]
include/grub/misc.h [new file with mode: 0644]
include/grub/mm.h [new file with mode: 0644]
include/grub/net.h [new file with mode: 0644]
include/grub/rescue.h [new file with mode: 0644]
include/grub/symbol.h [new file with mode: 0644]
include/grub/term.h [new file with mode: 0644]
include/grub/types.h [new file with mode: 0644]
include/grub/util/misc.h [new file with mode: 0644]
include/grub/util/resolve.h [new file with mode: 0644]
install-sh [new file with mode: 0644]
kern/device.c [new file with mode: 0644]
kern/disk.c [new file with mode: 0644]
kern/dl.c [new file with mode: 0644]
kern/err.c [new file with mode: 0644]
kern/file.c [new file with mode: 0644]
kern/fs.c [new file with mode: 0644]
kern/i386/dl.c [new file with mode: 0644]
kern/i386/pc/init.c [new file with mode: 0644]
kern/i386/pc/startup.S [new file with mode: 0644]
kern/loader.c [new file with mode: 0644]
kern/main.c [new file with mode: 0644]
kern/misc.c [new file with mode: 0644]
kern/mm.c [new file with mode: 0644]
kern/rescue.c [new file with mode: 0644]
kern/term.c [new file with mode: 0644]
loader/i386/pc/chainloader.c [new file with mode: 0644]
mkinstalldirs [new file with mode: 0644]
stamp-h.in [new file with mode: 0644]
term/i386/pc/console.c [new file with mode: 0644]
util/genmoddep.c [new file with mode: 0644]
util/i386/pc/grub-mkimage.c [new file with mode: 0644]
util/misc.c [new file with mode: 0644]
util/resolve.c [new file with mode: 0644]

diff --git a/.cvsignore b/.cvsignore
new file mode 100644 (file)
index 0000000..91983cf
--- /dev/null
@@ -0,0 +1,8 @@
+Makefile
+config.cache
+config.h
+config.log
+config.status
+stamp-h
+stamp-h1
+autom4te.cache
diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..aacc839
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Yoshinori K. Okuji designed and implemented everything.
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..eeb586b
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..be53288
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,4 @@
+2002-12-27  Yoshinori K. Okuji  <okuji@enbug.org>
+
+       * Changelog: New file.
+
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..228029e
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,157 @@
+-*- Text -*-
+
+This is the PUPA.  Welcome.
+
+This file contains instructions for compiling and installing the PUPA.
+
+The Requirements
+================
+
+PUPA depends on some software packages installed into your system. If
+you don't have any of them, please obtain and install them before
+configuring the PUPA.
+
+* GCC 2.95 or later
+* GNU Make
+* GNU binutils 2.9.1.0.23 or later
+* Other standard GNU/Unix tools
+
+If you'd like to develop PUPA, these below are also required.
+
+* Ruby 1.6 or later
+* Autoconf 2.53 or later
+
+Configuring the PUPA
+====================
+
+The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a
+file `config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+If you need to do unusual things to compile the package, please try to
+figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+The file `configure.ac' is used to create `configure' by a program
+called `autoconf'.  You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+
+Building the PUPA
+=================
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and
+     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.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  `cd' to the directory where you want the object files
+and executables to go and run the `configure' script.  `configure'
+automatically checks for the source code in the directory that
+`configure' is in and in `..'.
+
+
+Installation Names
+==================
+
+By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix by giving `configure' the option `--prefix=PATH'.
+
+You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If
+you give `configure' the option `--exec-prefix=PATH', the package will
+use PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for
+particular kinds of files.  Run `configure --help' for a list of the
+directories you can set and what kinds of files go in them.
+
+If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure'
+the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Please note, however, that the PUPA knows where it is located in the
+filesystem.  If you have installed it in an unusual location, the
+system might not work properly, or at all.  The chief utility of these
+options for the PUPA is to allow you to "install" in some alternate
+location, and then copy these to the actual root filesystem later.
+
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+
+Operation Controls
+==================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+     Use and save the results of the tests in FILE instead of
+     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
+     debugging `configure'.
+
+`--help'
+     Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--version'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
diff --git a/Makefile.in b/Makefile.in
new file mode 100644 (file)
index 0000000..9dfca54
--- /dev/null
@@ -0,0 +1,259 @@
+# -*- makefile -*-
+#
+# Copyright (C) 1994,1995,1996,1997,1998,1999,2000,2001  Free Software Foundation, Inc.
+# Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+#
+# This Makefile.in is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+### The configure script will replace these variables.
+
+SHELL = /bin/sh
+
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+pkgdatadir = $(datadir)/@PACKAGE_TARNAME@/$(host_cpu)-$(host_vendor)
+pkglibdir = $(libdir)/@PACKAGE_TARNAME@
+
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+
+host_cpu = @host_cpu@
+host_vendor = @host_vendor@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+
+mkinstalldirs = $(srcdir)/mkinstalldirs
+
+CC = @CC@
+CFLAGS = @CFLAGS@
+CPPFLAGS = -I. -Iinclude -I$(srcdir)/include -Wall -W
+BUILD_CC = @CC@
+BUILD_CFLAGS = -g -O2
+BUILD_CPPFLAGS = -I. -Iinclude -I$(srcdir)/include -Wall -W \
+       -DPUPA_DATADIR=\"$(pkgdatadir)\"
+OBJCOPY = @OBJCOPY@
+STRIP = @STRIP@
+NM = @NM@
+RUBY = @RUBY@
+
+### General variables.
+
+RMKFILES = $(addprefix conf/,i386-pc.rmk)
+MKFILES = $(patsubst %.rmk,%.mk,$(RMKFILES))
+
+COMMON_DISTFILES = AUTHORS COPYING ChangeLog INSTALL NEWS README \
+       THANKS TODO Makefile.in aclocal.m4 autogen.sh config.guess \
+       config.h.in config.sub configure configure.ac genkernsyms.sh \
+       genmk.rb genmodsrc.sh gensymlist.sh install-sh mkinstalldirs \
+       stamp-h.in
+
+BOOT_DISTFILES = $(addprefix boot/i386/pc/,boot.S diskboot.S)
+
+CONF_DISTFILES = $(RMKFILES) $(MKFILES)
+
+DISK_DISTFILES = $(addprefix disk/i386/pc/,biosdisk.c partition.c)
+
+FS_DISTFILES = $(addprefix fs/,fat.c)
+
+INCLUDE_DISTFILES = $(addprefix include/pupa/,boot.h device.h disk.h \
+         dl.h elf.h err.h file.h fs.h kernel.h loader.h misc.h mm.h \
+         net.h rescue.h symbol.h term.h types.h) \
+       $(addprefix include/pupa/util/,misc.h resolve.h) \
+       include/pupa/i386/types.h \
+       $(addprefix include/pupa/i386/pc/,biosdisk.h boot.h \
+         console.h init.h kernel.h loader.h memory.h partition.h)
+
+KERN_DISTFILES = $(addprefix kern/,device.c disk.c dl.c err.c file.c \
+         fs.c loader.c main.c misc.c mm.c rescue.c term.c) \
+       kern/i386/dl.c \
+       $(addprefix kern/i386/pc/,init.c startup.S)
+
+LOADER_DISTFILES = $(addprefix loader/i386/pc/,chainloader.c)
+
+TERM_DISTFILES = $(addprefix term/i386/pc/,console.c)
+
+UTIL_DISTFILES = $(addprefix util/,genmoddep.c misc.c resolve.c) \
+       util/i386/pc/pupa-mkimage.c
+
+DISTFILES = $(COMMON_DISTFILES) $(BOOT_DISTFILES) $(CONF_DISTFILES) \
+       $(DISK_DISTFILES) $(FS_DISTFILES) $(INCLUDE_DISTFILES) \
+       $(KERN_DISTFILES) $(LOADER_DISTFILES) $(TERM_DISTFILES) \
+       $(UTIL_DISTFILES)
+
+DATA = $(pkgdata_IMAGES) $(pkgdata_MODULES)
+PROGRAMS = $(bin_UTILITIES) $(sbin_UTILITIES)
+SCRIPTS = 
+
+CLEANFILES =
+MOSTLYCLEANFILES = 
+DISTCLEANFILES = config.status config.cache config.log config.h \
+       Makefile stamp-h include/pupa/cpu include/pupa/machine
+MAINTAINER_CLEANFILES = $(srcdir)/configure $(addprefix $(srcdir)/,$(MKFILES))
+
+# The default target.
+all: all-local
+
+### Include an arch-specific Makefile.
+$(addprefix $(srcdir)/,$(MKFILES)): %.mk: %.rmk genmk.rb
+       if test "x$(RUBY)" = x; then \
+         touch $@; \
+       else \
+         $(RUBY) $(srcdir)/genmk.rb < $< > $@; \
+       fi
+
+include $(srcdir)/conf/$(host_cpu)-$(host_vendor).mk
+
+### General targets.
+
+all-local: $(PROGRAMS) $(DATA) $(SCRIPTS)
+
+install: install-local
+
+install-local: all
+       $(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
+       @list='$(pkgdata_IMAGES) $(pkgdata_MODULES)'; for file in $$list; do \
+         if test -f "$$file"; then dir=; else dir="$(srcdir)"; fi; \
+         dest="`echo $$file | sed 's,.*/,,'`"; \
+         $(INSTALL_DATA) $$dir$$file $(DESTDIR)$(pkgdatadir)/$$dest; \
+       done
+       $(mkinstalldirs) $(DESTDIR)$(bindir)
+       @list='$(bin_UTILITIES)'; for file in $$list; do \
+         if test -f "$$file"; then dir=; else dir="$(srcdir)"; fi; \
+         dest="`echo $$file | sed 's,.*/,,'`"; \
+         $(INSTALL_PROGRAM) $$dir$$file $(DESTDIR)$(bindir)/$$dest; \
+       done
+
+install-strip:
+       $(MAKE) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" install
+
+uninstall:
+       @list='$(pkgdata_IMAGES) $(pkgdata_MODULES)'; for file in $$list; do \
+         dest="`echo $$file | sed 's,.*/,,'`"; \
+         rm -f $(DESTDIR)$(pkgdatadir)/$$dest; \
+       done
+       @list = '$(bin_UTILITIES)'; for file in $$list; do \
+         dest="`echo $$file | sed 's,.*/,,'`"; \
+         rm -f $(DESTDIR)$(bindir)/$$dest; \
+       done
+
+clean:
+       -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+mostlyclean: clean
+       -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+distclean: mostlyclean
+       -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+       -rm -rf $(srcdir)/autom4te.cache
+
+maintainer-clean: distclean
+       -test -z "$(MAINTAINER_CLEANFILES)" || rm -f $(MAINTAINER_CLEANFILES)
+
+info:
+
+dvi:
+
+distdir=$(PACKAGE_TARNAME)-$(PACKAGE_VERSION)
+
+distdir: $(DISTFILES)
+       -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir)
+       $(mkinstalldirs) $(distdir)
+       for i in $(DISTFILES); do \
+         dir=`echo "$$i" | sed 's:/[^/]*$$::'`; \
+         if test -d $(srcdir)/$$dir; then \
+           $(mkinstalldirs) $(distdir)/$$dir; \
+         fi; \
+         cp -p $(srcdir)/$$i $(distdir)/$$i || exit 1; \
+       done
+       chmod -R a+r $(distdir)
+
+GZIP_ENV = --best
+
+dist: distdir
+       tar chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir)
+
+distcheck: dist
+       -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir)
+       GZIP=$(GZIP_ENV) gzip -cd $(distdir).tar.gz | tar xf -
+       chmod -R a-w $(distdir)
+       chmod a+w $(distdir)
+       mkdir $(distdir)/=build
+       mkdir $(distdir)/=inst
+       chmod a-w $(distdir)
+       dc_instdir=`CDPATH=: && cd $(distdir)/=inst && pwd` \
+         && cd $(distdir)/=build \
+         && ../configure --srcdir=.. --prefix=$$dc_instdir \
+         && $(MAKE) all dvi check install uninstall \
+         && (test `find $$dc_instdir -type f -print | wc -l` -le 1 \
+            || (echo "Error: files left after uninstall" 1>&2; \
+                exit 1)) \
+         && $(MAKE) dist distclean \
+         && rm -f $(distdir).tar.gz \
+         && (test `find . -type f -print | wc -l` -eq 0 \
+            || (echo "Error: files left after distclean" 1>&2; \
+                exit 1))
+       -chmod -R a+w $(distdir) > /dev/null 2>&1; rm -rf $(distdir)
+       @echo "$(distdir).tar.gz is ready for distribution" | \
+         sed 'h;s/./=/g;p;x;p;x'
+
+check:
+
+.SUFFIX:
+.SUFFIX: .c .o .S .d
+
+# Regenerate configure and Makefile automatically.
+$(srcdir)/configure: configure.ac aclocal.m4
+       cd $(srcdir) && autoconf
+
+$(srcdir)/config.h.in: stamp-h.in
+$(srcdir)/stamp-h.in: configure.ac aclocal.m4
+       cd $(srcdir) && autoheader
+       echo timestamp > $(srcdir)/stamp-h.in
+
+config.h: stamp-h
+stamp-h: config.h.in config.status
+       ./config.status
+
+Makefile: Makefile.in config.status
+       ./config.status
+
+config.status: configure
+       ./config.status --recheck
+
+.PHONY: all install install-strip uninstall clean mostlyclean distclean
+.PHONY: maintainer-clean info dvi dist check
+
+# Prevent an overflow.
+.NOEXPORT:
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..65ce9a0
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,12 @@
+New in 0.6 - 2002-12-27, Yoshinori K. Okuji:
+
+* The chainloader and the FAT filesystem are modularized.
+
+* The structure of the source tree is a bit changed.
+
+* Support for building loadable modules is added.
+
+* Some generic parts of pupa-mkimage are segregated.
+
+* Some documentation files are added, according to the GNU Coding
+  Standards.
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..867f475
--- /dev/null
+++ b/README
@@ -0,0 +1,26 @@
+This is PUPA, the Preliminary Universal Programming Architecture for
+GRUB.  PUPA is a research project for the next generation of GNU GRUB.
+The most important goal is to make GNU GRUB cleaner, safer, more robust,
+more powerful, and more portable.
+
+See the file NEWS for a description of recent changes to PUPA.
+
+See the file INSTALL for instructions on how to build and install the
+PUPA data and program files.
+
+Please visit the official web page of PUPA, for more information.
+The URL is <http://www.nongnu.org/pupa/>.
+
+\f
+
+Because PUPA is still in developmental stage, PUPA is not for general
+use (yet). For now, you can install PUPA into a floppy by these
+instructions:
+
+$ configure && make
+$ ./pupa-mkimage -v -d . -o core.img chain fat
+$ dd if=boot.img of=/dev/fd0 bs=512 count=1
+$ dd if=core.img of=/dev/fd0 bs=512 seek=1
+
+It would be easier to use Bochs <http://bochs.sf.net/> than a real
+machine.
diff --git a/THANKS b/THANKS
new file mode 100644 (file)
index 0000000..6c02770
--- /dev/null
+++ b/THANKS
@@ -0,0 +1,16 @@
+PUPA would not be what it is today without the invaluable help of
+everybody who was kind enough to spend time testing it and reporting
+bugs.
+
+The following people made especially gracious contributions of their
+time and energy in helping to track down bugs, add new features, and
+generally assist in the PUPA maintainership process:
+
+NIIBE Yutaka <gniibe@m17n.org>
+Tsuneyoshi Yasuo <tuneyoshi@naic.co.jp>
+
+Also, we thank the projects GNU GRUB and GNU Automake. Some code were
+stolen from them.
+
+This project is supported by Information-technology Promotion Agency,
+Japan.
diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..cd57f71
--- /dev/null
+++ b/TODO
@@ -0,0 +1,37 @@
+-*- Mode: Outline -*-
+
+Before working on anything in this file, it's very important that you
+make contact with the core PUPA developers. Things herein might be
+slightly out of date or otherwise not easy to understand at first
+glance. So write to <pupa-devel@nongnu.org> first.
+
+Priorities:
+  Reported bugs generally have top priority.
+  Non-reported and non-encountered bugs (things we know don't work,
+    but don't really impede things) have lower priority.
+  Things in this file are ranked with one to three !; the more, the
+  higher priority.
+
+
+* Add more filesystems (such as ext2fs, ffs, and reiserfs). !
+
+* Add support for internationalization. !!!
+
+* Add more loaders (such as Multiboot, Linux and FreeBSD). !!
+
+* Implement an installer. !!!
+
+* Add more terminals (such as serial). !
+
+* Implement a normal mode. !!!
+
+* Write a manual.
+
+* Shrink the kernel code.
+
+* Add support for compressed files.
+
+* Add support for network devices.
+
+* Compress the core image and decompress it at loading time, to make it
+  smaller. ?
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644 (file)
index 0000000..9f8e1e7
--- /dev/null
@@ -0,0 +1,292 @@
+dnl pupa_ASM_USCORE checks if C symbols get an underscore after
+dnl compiling to assembler.
+dnl Written by Pavel Roskin. Based on grub_ASM_EXT_C written by
+dnl Erich Boleyn and modified by Yoshinori K. Okuji.
+AC_DEFUN(pupa_ASM_USCORE,
+[AC_REQUIRE([AC_PROG_CC])
+AC_MSG_CHECKING([if C symbols get an underscore after compilation])
+AC_CACHE_VAL(pupa_cv_asm_uscore,
+[cat > conftest.c <<\EOF
+int
+func (int *list)
+{
+  *list = 0;
+  return *list;
+}
+EOF
+
+if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -S conftest.c]) && test -s conftest.s; then
+  true
+else
+  AC_MSG_ERROR([${CC-cc} failed to produce assembly code])
+fi
+
+if grep _func conftest.s >/dev/null 2>&1; then
+  pupa_cv_asm_uscore=yes
+else
+  pupa_cv_asm_uscore=no
+fi
+
+rm -f conftest*])
+
+if test "x$pupa_cv_asm_uscore" = xyes; then
+  AC_DEFINE_UNQUOTED([HAVE_ASM_USCORE], $pupa_cv_asm_uscore,
+    [Define if C symbols get an underscore after compilation])
+fi
+
+AC_MSG_RESULT([$pupa_cv_asm_uscore])
+])
+
+
+dnl Some versions of `objcopy -O binary' vary their output depending
+dnl on the link address.
+AC_DEFUN(pupa_PROG_OBJCOPY_ABSOLUTE,
+[AC_MSG_CHECKING([whether ${OBJCOPY} works for absolute addresses])
+AC_CACHE_VAL(pupa_cv_prog_objcopy_absolute,
+[cat > conftest.c <<\EOF
+void
+cmain (void)
+{
+   *((int *) 0x1000) = 2;
+}
+EOF
+
+if AC_TRY_EVAL(ac_compile) && test -s conftest.o; then :
+else
+  AC_MSG_ERROR([${CC-cc} cannot compile C source code])
+fi
+pupa_cv_prog_objcopy_absolute=yes
+for link_addr in 2000 8000 7C00; do
+  if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -nostdlib -Wl,-N -Wl,-Ttext -Wl,$link_addr conftest.o -o conftest.exec]); then :
+  else
+    AC_MSG_ERROR([${CC-cc} cannot link at address $link_addr])
+  fi
+  if AC_TRY_COMMAND([${OBJCOPY-objcopy} -O binary conftest.exec conftest]); then :
+  else
+    AC_MSG_ERROR([${OBJCOPY-objcopy} cannot create binary files])
+  fi
+  if test ! -f conftest.old || AC_TRY_COMMAND([cmp -s conftest.old conftest]); then
+    mv -f conftest conftest.old
+  else
+    pupa_cv_prog_objcopy_absolute=no
+    break
+  fi
+done
+rm -f conftest*])
+AC_MSG_RESULT([$pupa_cv_prog_objcopy_absolute])
+
+if test "x$pupa_cv_prog_objcopy_absolute" = xno; then
+  AC_MSG_ERROR([PUPA requires a working absolute objcopy; upgrade your binutils])
+fi
+])
+
+
+dnl Mass confusion!
+dnl Older versions of GAS interpret `.code16' to mean ``generate 32-bit
+dnl instructions, but implicitly insert addr32 and data32 bytes so
+dnl that the code works in real mode''.
+dnl
+dnl Newer versions of GAS interpret `.code16' to mean ``generate 16-bit
+dnl instructions,'' which seems right.  This requires the programmer
+dnl to explicitly insert addr32 and data32 instructions when they want
+dnl them.
+dnl
+dnl We only support the newer versions, because the old versions cause
+dnl major pain, by requiring manual assembly to get 16-bit instructions into
+dnl asm files.
+AC_DEFUN(pupa_I386_ASM_ADDR32,
+[AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE([pupa_I386_ASM_PREFIX_REQUIREMENT])
+AC_MSG_CHECKING([for .code16 addr32 assembler support])
+AC_CACHE_VAL(pupa_cv_i386_asm_addr32,
+[cat > conftest.s.in <<\EOF
+       .code16
+l1:    @ADDR32@        movb    %al, l1
+EOF
+
+if test "x$pupa_cv_i386_asm_prefix_requirement" = xyes; then
+  sed -e s/@ADDR32@/addr32/ < conftest.s.in > conftest.s
+else
+  sed -e s/@ADDR32@/addr32\;/ < conftest.s.in > conftest.s
+fi
+
+if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then
+  pupa_cv_i386_asm_addr32=yes
+else
+  pupa_cv_i386_asm_addr32=no
+fi
+
+rm -f conftest*])
+
+AC_MSG_RESULT([$pupa_cv_i386_asm_addr32])])
+
+
+dnl Later versions of GAS requires that addr32 and data32 prefixes
+dnl appear in the same lines as the instructions they modify, while
+dnl earlier versions requires that they appear in separate lines.
+AC_DEFUN(pupa_I386_ASM_PREFIX_REQUIREMENT,
+[AC_REQUIRE([AC_PROG_CC])
+AC_MSG_CHECKING(dnl
+[whether addr32 must be in the same line as the instruction])
+AC_CACHE_VAL(pupa_cv_i386_asm_prefix_requirement,
+[cat > conftest.s <<\EOF
+       .code16
+l1:    addr32  movb    %al, l1
+EOF
+
+if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then
+  pupa_cv_i386_asm_prefix_requirement=yes
+else
+  pupa_cv_i386_asm_prefix_requirement=no
+fi
+
+rm -f conftest*])
+
+if test "x$pupa_cv_i386_asm_prefix_requirement" = xyes; then
+  pupa_tmp_addr32="addr32"
+  pupa_tmp_data32="data32"
+else
+  pupa_tmp_addr32="addr32;"
+  pupa_tmp_data32="data32;"
+fi
+
+AC_DEFINE_UNQUOTED([ADDR32], $pupa_tmp_addr32,
+  [Define it to \"addr32\" or \"addr32;\" to make GAS happy])
+AC_DEFINE_UNQUOTED([DATA32], $pupa_tmp_data32,
+  [Define it to \"data32\" or \"data32;\" to make GAS happy])
+
+AC_MSG_RESULT([$pupa_cv_i386_asm_prefix_requirement])])
+
+
+dnl Older versions of GAS require that absolute indirect calls/jumps are
+dnl not prefixed with `*', while later versions warn if not prefixed.
+AC_DEFUN(pupa_I386_ASM_ABSOLUTE_WITHOUT_ASTERISK,
+[AC_REQUIRE([AC_PROG_CC])
+AC_MSG_CHECKING(dnl
+[whether an absolute indirect call/jump must not be prefixed with an asterisk])
+AC_CACHE_VAL(pupa_cv_i386_asm_absolute_without_asterisk,
+[cat > conftest.s <<\EOF
+       lcall   *(offset)       
+offset:
+       .long   0
+       .word   0
+EOF
+
+if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then
+  pupa_cv_i386_asm_absolute_without_asterisk=no
+else
+  pupa_cv_i386_asm_absolute_without_asterisk=yes
+fi
+
+rm -f conftest*])
+
+if test "x$pupa_cv_i386_asm_absolute_without_asterisk" = xyes; then
+  AC_DEFINE([ABSOLUTE_WITHOUT_ASTERISK], 1,
+           [Define it if GAS requires that absolute indirect calls/jumps are not prefixed with an asterisk])
+fi
+
+AC_MSG_RESULT([$pupa_cv_i386_asm_absolute_without_asterisk])])
+
+
+dnl Check what symbol is defined as a start symbol.
+dnl Written by Yoshinori K. Okuji.
+AC_DEFUN(pupa_CHECK_START_SYMBOL,
+[AC_REQUIRE([AC_PROG_CC])
+AC_MSG_CHECKING([if start is defined by the compiler])
+AC_CACHE_VAL(pupa_cv_check_start_symbol,
+[AC_TRY_LINK([], [asm ("incl start")],
+   pupa_cv_check_start_symbol=yes,
+   pupa_cv_check_start_symbol=no)])
+
+AC_MSG_RESULT([$pupa_cv_check_start_symbol])
+
+AC_MSG_CHECKING([if _start is defined by the compiler])
+AC_CACHE_VAL(pupa_cv_check_uscore_start_symbol,
+[AC_TRY_LINK([], [asm ("incl _start")],
+   pupa_cv_check_uscore_start_symbol=yes,
+   pupa_cv_check_uscore_start_symbol=no)])
+
+AC_MSG_RESULT([$pupa_cv_check_uscore_start_symbol])
+
+AH_TEMPLATE([START_SYMBOL], [Define it to either start or _start])
+
+if test "x$pupa_cv_check_start_symbol" = xyes; then
+  AC_DEFINE([START_SYMBOL], [start])
+elif test "x$pupa_cv_check_uscore_start_symbol" = xyes; then
+  AC_DEFINE([START_SYMBOL], [_start])
+else
+  AC_MSG_ERROR([neither start nor _start is defined])
+fi
+])
+
+dnl Check what symbol is defined as a bss start symbol.
+dnl Written by Michael Hohmoth and Yoshinori K. Okuji.
+AC_DEFUN(pupa_CHECK_BSS_START_SYMBOL,
+[AC_REQUIRE([AC_PROG_CC])
+AC_MSG_CHECKING([if __bss_start is defined by the compiler])
+AC_CACHE_VAL(pupa_cv_check_uscore_uscore_bss_start_symbol,
+[AC_TRY_LINK([], [asm ("incl __bss_start")],
+   pupa_cv_check_uscore_uscore_bss_start_symbol=yes,
+   pupa_cv_check_uscore_uscore_bss_start_symbol=no)])
+
+AC_MSG_RESULT([$pupa_cv_check_uscore_uscore_bss_start_symbol])
+
+AC_MSG_CHECKING([if edata is defined by the compiler])
+AC_CACHE_VAL(pupa_cv_check_edata_symbol,
+[AC_TRY_LINK([], [asm ("incl edata")],
+   pupa_cv_check_edata_symbol=yes,
+   pupa_cv_check_edata_symbol=no)])
+
+AC_MSG_RESULT([$pupa_cv_check_edata_symbol])
+
+AC_MSG_CHECKING([if _edata is defined by the compiler])
+AC_CACHE_VAL(pupa_cv_check_uscore_edata_symbol,
+[AC_TRY_LINK([], [asm ("incl _edata")],
+   pupa_cv_check_uscore_edata_symbol=yes,
+   pupa_cv_check_uscore_edata_symbol=no)])
+
+AC_MSG_RESULT([$pupa_cv_check_uscore_edata_symbol])
+
+AH_TEMPLATE([BSS_START_SYMBOL], [Define it to one of __bss_start, edata and _edata])
+
+if test "x$pupa_cv_check_uscore_uscore_bss_start_symbol" = xyes; then
+  AC_DEFINE([BSS_START_SYMBOL], [__bss_start])
+elif test "x$pupa_cv_check_edata_symbol" = xyes; then
+  AC_DEFINE([BSS_START_SYMBOL], [edata])
+elif test "x$pupa_cv_check_uscore_edata_symbol" = xyes; then
+  AC_DEFINE([BSS_START_SYMBOL], [_edata])
+else
+  AC_MSG_ERROR([none of __bss_start, edata or _edata is defined])
+fi
+])
+
+dnl Check what symbol is defined as an end symbol.
+dnl Written by Yoshinori K. Okuji.
+AC_DEFUN(pupa_CHECK_END_SYMBOL,
+[AC_REQUIRE([AC_PROG_CC])
+AC_MSG_CHECKING([if end is defined by the compiler])
+AC_CACHE_VAL(pupa_cv_check_end_symbol,
+[AC_TRY_LINK([], [asm ("incl end")],
+   pupa_cv_check_end_symbol=yes,
+   pupa_cv_check_end_symbol=no)])
+
+AC_MSG_RESULT([$pupa_cv_check_end_symbol])
+
+AC_MSG_CHECKING([if _end is defined by the compiler])
+AC_CACHE_VAL(pupa_cv_check_uscore_end_symbol,
+[AC_TRY_LINK([], [asm ("incl _end")],
+   pupa_cv_check_uscore_end_symbol=yes,
+   pupa_cv_check_uscore_end_symbol=no)])
+
+AC_MSG_RESULT([$pupa_cv_check_uscore_end_symbol])
+
+AH_TEMPLATE([END_SYMBOL], [Define it to either end or _end])
+
+if test "x$pupa_cv_check_end_symbol" = xyes; then
+  AC_DEFINE([END_SYMBOL], [end])
+elif test "x$pupa_cv_check_uscore_end_symbol" = xyes; then
+  AC_DEFINE([END_SYMBOL], [_end])
+else
+  AC_MSG_ERROR([neither end nor _end is defined])
+fi
+])
diff --git a/autogen.sh b/autogen.sh
new file mode 100644 (file)
index 0000000..387bea7
--- /dev/null
@@ -0,0 +1,11 @@
+#! /bin/sh
+
+set -e
+
+autoconf
+autoheader
+for rmk in conf/*.rmk; do
+  ruby genmk.rb < $rmk > `echo $rmk | sed 's/\.rmk$/.mk/'`
+done
+
+exit 0
diff --git a/boot/i386/pc/boot.S b/boot/i386/pc/boot.S
new file mode 100644 (file)
index 0000000..dd3c667
--- /dev/null
@@ -0,0 +1,487 @@
+/* -*-Asm-*- */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 1999,2000,2001   Free Software Foundation, Inc.
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/boot.h>
+#include <pupa/machine/boot.h>
+       
+/*
+ *  defines for the code go here
+ */
+
+       /* Absolute addresses
+          This makes the assembler generate the address without support
+          from the linker. (ELF can't relocate 16-bit addresses!) */
+#define ABS(x) (x-_start+0x7c00)
+
+       /* Print message string */
+#define MSG(x) movw $ABS(x), %si; call message
+
+       /* XXX: binutils-2.9.1.0.x doesn't produce a short opcode for this. */
+#define        MOV_MEM_TO_AL(x)        .byte 0xa0;  .word x
+       
+       .file   "boot.S"
+
+       .text
+
+       /* Tell GAS to generate 16-bit instructions so that this code works
+          in real mode. */
+       .code16
+
+.globl _start; _start:
+       /*
+        * _start is loaded at 0x7c00 and is jumped to with CS:IP 0:0x7c00
+        */
+
+       /*
+        * Beginning of the sector is compatible with the FAT/HPFS BIOS
+        * parameter block.
+        */
+
+       jmp     after_BPB
+       nop     /* do I care about this ??? */
+
+       /*
+        * This space is for the BIOS parameter block!!!!  Don't change
+        * the first jump, nor start the code anywhere but right after
+        * this area.
+        */
+
+       . = _start + 4
+
+       /* scratch space */
+mode:
+       .byte   0
+disk_address_packet:   
+sectors:
+       .long   0
+heads:
+       .long   0
+cylinders:
+       .word   0
+sector_start:
+       .byte   0
+head_start:
+       .byte   0
+cylinder_start:
+       .word   0
+       /* more space... */
+
+       . = _start + PUPA_BOOT_MACHINE_BPBEND
+
+       /*
+        * End of BIOS parameter block.
+        */
+
+boot_version:  
+       .byte   PUPA_BOOT_VERSION_MAJOR, PUPA_BOOT_VERSION_MINOR
+boot_drive:    
+       .byte 0xff      /* the disk to load kernel from */
+                       /* 0xff means use the boot drive */
+force_lba:
+       .byte   0
+kernel_address:
+       .word   PUPA_BOOT_MACHINE_KERNEL_ADDR
+kernel_sector:
+       .long   1
+kernel_segment:
+       .word   PUPA_BOOT_MACHINE_KERNEL_SEG
+
+after_BPB:
+
+/* general setup */
+       cli             /* we're not safe here! */
+
+       /*
+        * ljmp to the next instruction because some bogus BIOSes
+        * jump to 07C0:0000 instead of 0000:7C00.
+        */
+       ljmp    $0, $ABS(real_start)
+
+real_start:    
+
+       /* set up %ds and %ss as offset from 0 */
+       xorw    %ax, %ax
+       movw    %ax, %ds
+       movw    %ax, %ss
+
+       /* set up the REAL stack */
+       movw    $PUPA_BOOT_MACHINE_STACK_SEG, %sp
+
+       sti             /* we're safe again */
+
+       /*
+        *  Check if we have a forced disk reference here
+        */
+       MOV_MEM_TO_AL(ABS(boot_drive))  /* movb ABS(boot_drive), %al */
+       cmpb    $0xff, %al
+       je      1f
+       movb    %al, %dl
+1:
+       /* save drive reference first thing! */
+       pushw   %dx
+
+       /* print a notification message on the screen */
+       MSG(notification_string)
+
+       /* do not probe LBA if the drive is a floppy */
+       testb   $PUPA_BOOT_MACHINE_BIOS_HD_FLAG, %dl
+       jz      chs_mode
+                       
+       /* check if LBA is supported */
+       movb    $0x41, %ah
+       movw    $0x55aa, %bx
+       int     $0x13
+
+       /* 
+        *  %dl may have been clobbered by INT 13, AH=41H.
+        *  This happens, for example, with AST BIOS 1.04.
+        */
+       popw    %dx
+       pushw   %dx
+
+       /* use CHS if fails */
+       jc      chs_mode
+       cmpw    $0xaa55, %bx
+       jne     chs_mode
+
+       /* check if AH=0x42 is supported if FORCE_LBA is zero */
+       MOV_MEM_TO_AL(ABS(force_lba))   /* movb ABS(force_lba), %al */
+       testb   %al, %al
+       jnz     lba_mode
+       andw    $1, %cx
+       jz      chs_mode
+       
+lba_mode:
+       /* save the total number of sectors */
+       movl    0x10(%si), %ecx
+
+       /* set %si to the disk address packet */
+       movw    $ABS(disk_address_packet), %si
+
+       /* set the mode to non-zero */
+       movb    $1, -1(%si)
+       
+       movl    ABS(kernel_sector), %ebx
+
+       /* the size and the reserved byte */
+       movw    $0x0010, (%si)
+
+       /* the blocks */
+       movw    $1, 2(%si)
+       
+       /* the absolute address (low 32 bits) */
+       movl    %ebx, 8(%si)
+
+       /* the segment of buffer address */
+       movw    $PUPA_BOOT_MACHINE_BUFFER_SEG, 6(%si)
+
+       xorl    %eax, %eax
+       movw    %ax, 4(%si)
+       movl    %eax, 12(%si)
+       
+/*
+ * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory
+ *     Call with       %ah = 0x42
+ *                     %dl = drive number
+ *                     %ds:%si = segment:offset of disk address packet
+ *     Return:
+ *                     %al = 0x0 on success; err code on failure
+ */
+
+       movb    $0x42, %ah
+       int     $0x13
+
+       /* LBA read is not supported, so fallback to CHS.  */
+       jc      chs_mode
+
+       movw    $PUPA_BOOT_MACHINE_BUFFER_SEG, %bx
+       jmp     copy_buffer
+               
+chs_mode:      
+       /*
+        *  Determine the hard disk geometry from the BIOS!
+        *  We do this first, so that LS-120 IDE floppies work correctly.
+        */
+       movb    $8, %ah
+       int     $0x13
+       jnc     final_init
+
+       /*
+        *  The call failed, so maybe use the floppy probe instead.
+        */
+       testb   $PUPA_BOOT_MACHINE_BIOS_HD_FLAG, %dl
+       jz      floppy_probe
+
+       /* Nope, we definitely have a hard disk, and we're screwed. */
+       jmp     hd_probe_error
+
+final_init:
+       
+       movw    $ABS(sectors), %si
+
+       /* set the mode to zero */
+       movb    $0, -1(%si)
+       
+       /* save number of heads */
+       xorl    %eax, %eax
+       movb    %dh, %al
+       incw    %ax
+       movl    %eax, 4(%si)
+
+       xorw    %dx, %dx
+       movb    %cl, %dl
+       shlw    $2, %dx
+       movb    %ch, %al
+       movb    %dh, %ah
+
+       /* save number of cylinders */
+       incw    %ax
+       movw    %ax, 8(%si)
+
+       xorw    %ax, %ax
+       movb    %dl, %al
+       shrb    $2, %al
+
+       /* save number of sectors */
+       movl    %eax, (%si)
+
+setup_sectors:
+       /* load logical sector start (bottom half) */
+       movl    ABS(kernel_sector), %eax
+
+       /* zero %edx */
+       xorl    %edx, %edx
+
+       /* divide by number of sectors */
+       divl    (%si)
+
+       /* save sector start */
+       movb    %dl, 10(%si)
+
+       xorl    %edx, %edx      /* zero %edx */
+       divl    4(%si)          /* divide by number of heads */
+
+       /* save head start */
+       movb    %dl, 11(%si)
+
+       /* save cylinder start */
+       movw    %ax, 12(%si)
+
+       /* do we need too many cylinders? */
+       cmpw    8(%si), %ax
+       jge     geometry_error
+
+/*
+ *  This is the loop for taking care of BIOS geometry translation (ugh!)
+ */
+
+       /* get high bits of cylinder */
+       movb    13(%si), %dl
+
+       shlb    $6, %dl         /* shift left by 6 bits */
+       movb    10(%si), %cl    /* get sector */
+
+       incb    %cl             /* normalize sector (sectors go
+                                       from 1-N, not 0-(N-1) ) */
+       orb     %dl, %cl        /* composite together */
+       movb    12(%si), %ch    /* sector+hcyl in cl, cylinder in ch */
+
+       /* restore %dx */
+       popw    %dx
+       
+       /* head number */
+       movb    11(%si), %dh
+
+/*
+ * BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
+ *     Call with       %ah = 0x2
+ *                     %al = number of sectors
+ *                     %ch = cylinder
+ *                     %cl = sector (bits 6-7 are high bits of "cylinder")
+ *                     %dh = head
+ *                     %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
+ *                     %es:%bx = segment:offset of buffer
+ *     Return:
+ *                     %al = 0x0 on success; err code on failure
+ */
+
+       movw    $PUPA_BOOT_MACHINE_BUFFER_SEG, %bx
+       movw    %bx, %es        /* load %es segment with disk buffer */
+
+       xorw    %bx, %bx        /* %bx = 0, put it at 0 in the segment */
+       movw    $0x0201, %ax    /* function 2 */
+       int     $0x13
+
+       jc      read_error
+
+       movw    %es, %bx
+       
+copy_buffer:
+       movw    ABS(kernel_segment), %es
+
+       /*
+        * We need to save %cx and %si because the startup code in
+        * kernel uses them without initializing them.
+        */
+       pusha
+       pushw   %ds
+       
+       movw    $0x100, %cx
+       movw    %bx, %ds
+       xorw    %si, %si
+       xorw    %di, %di
+       
+       cld
+       
+       rep
+       movsw
+
+       popw    %ds
+       popa
+
+       /* boot kernel */
+       jmp     *(kernel_address)
+
+/* END OF MAIN LOOP */
+
+/*
+ * BIOS Geometry translation error (past the end of the disk geometry!).
+ */
+geometry_error:
+       MSG(geometry_error_string)
+       jmp     general_error
+
+/*
+ * Disk probe failure.
+ */
+hd_probe_error:
+       MSG(hd_probe_error_string)
+       jmp     general_error
+
+/*
+ * Read error on the disk.
+ */
+read_error:
+       MSG(read_error_string)
+
+general_error:
+       MSG(general_error_string)
+
+/* go here when you need to stop the machine hard after an error condition */
+stop:  jmp     stop
+
+notification_string:   .string "PUPA "
+geometry_error_string: .string "Geom"
+hd_probe_error_string: .string "Hard Disk"
+read_error_string:     .string "Read"
+general_error_string:  .string " Error"
+
+/*
+ * message: write the string pointed to by %si
+ *
+ *   WARNING: trashes %si, %ax, and %bx
+ */
+
+       /*
+        * Use BIOS "int 10H Function 0Eh" to write character in teletype mode
+        *      %ah = 0xe       %al = character
+        *      %bh = page      %bl = foreground color (graphics modes)
+        */
+1:
+       movw    $0x0001, %bx
+       movb    $0xe, %ah
+       int     $0x10           /* display a byte */
+message:
+       lodsb
+       cmpb    $0, %al
+       jne     1b      /* if not end of string, jmp to display */
+       ret
+
+       /*
+        *  Windows NT breaks compatibility by embedding a magic
+        *  number here.
+        */
+
+       . = _start + PUPA_BOOT_MACHINE_WINDOWS_NT_MAGIC
+nt_magic:      
+       .long 0
+       .word 0
+
+       /*
+        *  This is where an MBR would go if on a hard disk.  The code
+        *  here isn't even referenced unless we're on a floppy.  Kinda
+        *  sneaky, huh?
+        */
+
+part_start:    
+       . = _start + PUPA_BOOT_MACHINE_PART_START
+
+probe_values:
+       .byte   36, 18, 15, 9, 0
+
+floppy_probe:
+/*
+ *  Perform floppy probe.
+ */
+
+       movw    $ABS(probe_values-1), %si
+
+probe_loop:
+       /* reset floppy controller INT 13h AH=0 */
+       xorw    %ax, %ax
+       int     $0x13
+
+       incw    %si
+       movb    (%si), %cl
+
+       /* if number of sectors is 0, display error and die */
+       cmpb    $0, %cl
+       jne     1f
+
+/*
+ * Floppy disk probe failure.
+ */
+       MSG(fd_probe_error_string)
+       jmp     general_error
+
+fd_probe_error_string: .string "Floppy"
+
+1:
+       /* perform read */
+       movw    $PUPA_BOOT_MACHINE_BUFFER_SEG, %bx
+       movw    $0x201, %ax
+       movb    $0, %ch
+       movb    $0, %dh
+       int     $0x13
+
+       /* if error, jump to "probe_loop" */
+       jc      probe_loop
+
+       /* %cl is already the correct value! */
+       movb    $1, %dh
+       movb    $79, %ch
+
+       jmp     final_init
+
+       . = _start + PUPA_BOOT_MACHINE_PART_END
+
+/* the last 2 bytes in the sector 0 contain the signature */
+       .word   PUPA_BOOT_MACHINE_SIGNATURE
diff --git a/boot/i386/pc/diskboot.S b/boot/i386/pc/diskboot.S
new file mode 100644 (file)
index 0000000..da1e02a
--- /dev/null
@@ -0,0 +1,387 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 1999,2000,2001   Free Software Foundation, Inc.
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/machine/boot.h>
+       
+/*
+ *  defines for the code go here
+ */
+
+       /* Absolute addresses
+          This makes the assembler generate the address without support
+          from the linker. (ELF can't relocate 16-bit addresses!) */
+#define ABS(x) (x-_start+PUPA_BOOT_MACHINE_KERNEL_ADDR)
+       
+       /* Print message string */
+#define MSG(x) movw $ABS(x), %si; call message
+
+       .file   "diskboot.S"
+
+       .text
+
+       /* Tell GAS to generate 16-bit instructions so that this code works
+          in real mode. */
+       .code16
+
+       .globl  start, _start
+start:
+_start:        
+       /*
+        * _start is loaded at 0x2000 and is jumped to with
+        * CS:IP 0:0x2000 in kernel.
+        */
+
+       /* 
+        * we continue to use the stack for boot.img and assume that
+        * some registers are set to correct values. See boot.S
+        * for more information.
+        */
+       
+       /* save drive reference first thing! */
+       pushw   %dx
+
+       /* print a notification message on the screen */
+       pushw   %si
+       MSG(notification_string)
+       popw    %si
+       
+       /* this sets up for the first run through "bootloop" */
+       movw    $ABS(firstlist - PUPA_BOOT_MACHINE_LIST_SIZE), %di
+
+       /* save the sector number of the second sector in %ebp */
+       movl    (%di), %ebp
+
+        /* this is the loop for reading the rest of the kernel in */
+bootloop:
+
+       /* check the number of sectors to read */
+       cmpw    $0, 4(%di)
+
+       /* if zero, go to the start function */
+       je      bootit
+
+setup_sectors: 
+       /* check if we use LBA or CHS */
+       cmpb    $0, -1(%si)
+
+       /* jump to chs_mode if zero */
+       je      chs_mode
+
+lba_mode:      
+       /* load logical sector start */
+       movl    (%di), %ebx
+
+       /* the maximum is limited to 0x7f because of Phoenix EDD */
+       xorl    %eax, %eax
+       movb    $0x7f, %al
+
+       /* how many do we really want to read? */
+       cmpw    %ax, 4(%di)     /* compare against total number of sectors */
+
+       /* which is greater? */
+       jg      1f
+
+       /* if less than, set to total */
+       movw    4(%di), %ax
+
+1:     
+       /* subtract from total */
+       subw    %ax, 4(%di)
+
+       /* add into logical sector start */
+       addl    %eax, (%di)
+
+       /* set up disk address packet */
+
+       /* the size and the reserved byte */
+       movw    $0x0010, (%si)
+
+       /* the number of sectors */
+       movw    %ax, 2(%si)
+
+       /* the absolute address (low 32 bits) */
+       movl    %ebx, 8(%si)
+
+       /* the segment of buffer address */
+       movw    $PUPA_BOOT_MACHINE_BUFFER_SEG, 6(%si)
+
+       /* save %ax from destruction! */
+       pushw   %ax
+
+       /* zero %eax */
+       xorl    %eax, %eax
+
+       /* the offset of buffer address */
+       movw    %ax, 4(%si)
+
+       /* the absolute address (high 32 bits) */
+       movl    %eax, 12(%si)
+
+
+/*
+ * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory
+ *     Call with       %ah = 0x42
+ *                     %dl = drive number
+ *                     %ds:%si = segment:offset of disk address packet
+ *     Return:
+ *                     %al = 0x0 on success; err code on failure
+ */
+
+       movb    $0x42, %ah
+       int     $0x13
+
+       jc      read_error
+
+       movw    $PUPA_BOOT_MACHINE_BUFFER_SEG, %bx
+       jmp     copy_buffer
+                       
+chs_mode:      
+       /* load logical sector start (bottom half) */
+       movl    (%di), %eax
+
+       /* zero %edx */
+       xorl    %edx, %edx
+
+       /* divide by number of sectors */
+       divl    (%si)
+
+       /* save sector start */
+       movb    %dl, 10(%si)
+
+       xorl    %edx, %edx      /* zero %edx */
+       divl    4(%si)          /* divide by number of heads */
+
+       /* save head start */
+       movb    %dl, 11(%si)
+
+       /* save cylinder start */
+       movw    %ax, 12(%si)
+
+       /* do we need too many cylinders? */
+       cmpw    8(%si), %ax
+       jge     geometry_error
+
+       /* determine the maximum sector length of this read */
+       movw    (%si), %ax      /* get number of sectors per track/head */
+
+       /* subtract sector start */
+       subb    10(%si), %al
+
+       /* how many do we really want to read? */
+       cmpw    %ax, 4(%di)     /* compare against total number of sectors */
+
+
+       /* which is greater? */
+       jg      2f
+
+       /* if less than, set to total */
+       movw    4(%di), %ax
+
+2:     
+       /* subtract from total */
+       subw    %ax, 4(%di)
+
+       /* add into logical sector start */
+       addl    %eax, (%di)
+
+/*
+ *  This is the loop for taking care of BIOS geometry translation (ugh!)
+ */
+
+       /* get high bits of cylinder */
+       movb    13(%si), %dl
+
+       shlb    $6, %dl         /* shift left by 6 bits */
+       movb    10(%si), %cl    /* get sector */
+
+       incb    %cl             /* normalize sector (sectors go
+                                       from 1-N, not 0-(N-1) ) */
+       orb     %dl, %cl        /* composite together */
+       movb    12(%si), %ch    /* sector+hcyl in cl, cylinder in ch */
+
+       /* restore %dx */
+       popw    %dx
+       pushw   %dx
+
+       /* head number */
+       movb    11(%si), %dh
+
+       pushw   %ax     /* save %ax from destruction! */
+
+/*
+ * BIOS call "INT 0x13 Function 0x2" to read sectors from disk into memory
+ *     Call with       %ah = 0x2
+ *                     %al = number of sectors
+ *                     %ch = cylinder
+ *                     %cl = sector (bits 6-7 are high bits of "cylinder")
+ *                     %dh = head
+ *                     %dl = drive (0x80 for hard disk, 0x0 for floppy disk)
+ *                     %es:%bx = segment:offset of buffer
+ *     Return:
+ *                     %al = 0x0 on success; err code on failure
+ */
+
+       movw    $PUPA_BOOT_MACHINE_BUFFER_SEG, %bx
+       movw    %bx, %es        /* load %es segment with disk buffer */
+
+       xorw    %bx, %bx        /* %bx = 0, put it at 0 in the segment */
+       movb    $0x2, %ah       /* function 2 */
+       int     $0x13
+
+       jc      read_error
+
+       /* save source segment */
+       movw    %es, %bx
+       
+copy_buffer:   
+
+       /* load addresses for copy from disk buffer to destination */
+       movw    6(%di), %es     /* load destination segment */
+
+       /* restore %ax */
+       popw    %ax
+
+       /* determine the next possible destination address (presuming
+               512 byte sectors!) */
+       shlw    $5, %ax         /* shift %ax five bits to the left */
+       addw    %ax, 6(%di)     /* add the corrected value to the destination
+                                  address for next time */
+
+       /* save addressing regs */
+       pusha
+       pushw   %ds
+
+       /* get the copy length */
+       shlw    $3, %ax
+       movw    %ax, %cx
+
+       xorw    %di, %di        /* zero offset of destination addresses */
+       xorw    %si, %si        /* zero offset of source addresses */
+       movw    %bx, %ds        /* restore the source segment */
+
+       cld             /* sets the copy direction to forward */
+
+       /* perform copy */
+       rep             /* sets a repeat */
+       movsw           /* this runs the actual copy */
+
+       /* restore addressing regs and print a dot with correct DS 
+          (MSG modifies SI, which is saved, and unused AX and BX) */
+       popw    %ds
+       MSG(notification_step)
+       popa
+
+       /* check if finished with this dataset */
+       cmpw    $0, 4(%di)
+       jne     setup_sectors
+
+       /* update position to load from */
+       subw    $PUPA_BOOT_MACHINE_LIST_SIZE, %di
+
+       /* jump to bootloop */
+       jmp     bootloop
+
+/* END OF MAIN LOOP */
+
+bootit:
+       /* print a newline */
+       MSG(notification_done)
+       popw    %dx     /* this makes sure %dl is our "boot" drive */
+       ljmp    $0, $(PUPA_BOOT_MACHINE_KERNEL_ADDR + 0x200)
+
+
+/*
+ * BIOS Geometry translation error (past the end of the disk geometry!).
+ */
+geometry_error:
+       MSG(geometry_error_string)
+       jmp     general_error
+
+/*
+ * Read error on the disk.
+ */
+read_error:
+       MSG(read_error_string)
+
+general_error:
+       MSG(general_error_string)
+
+/* go here when you need to stop the machine hard after an error condition */
+stop:  jmp     stop
+
+notification_string:   .string "Loading kernel"
+
+notification_step:     .string "."
+notification_done:     .string "\r\n"
+       
+geometry_error_string: .string "Geom"
+read_error_string:     .string "Read"
+general_error_string:  .string " Error"
+
+/*
+ * message: write the string pointed to by %si
+ *
+ *   WARNING: trashes %si, %ax, and %bx
+ */
+
+       /*
+        * Use BIOS "int 10H Function 0Eh" to write character in teletype mode
+        *      %ah = 0xe       %al = character
+        *      %bh = page      %bl = foreground color (graphics modes)
+        */
+1:
+       movw    $0x0001, %bx
+       movb    $0xe, %ah
+       int     $0x10           /* display a byte */
+
+       incw    %si
+message:
+       movb    (%si), %al
+       cmpb    $0, %al
+       jne     1b      /* if not end of string, jmp to display */
+       ret
+lastlist:
+
+/*
+ *  This area is an empty space between the main body of code below which
+ *  grows up (fixed after compilation, but between releases it may change
+ *  in size easily), and the lists of sectors to read, which grows down
+ *  from a fixed top location.
+ */
+
+       .word 0
+       .word 0
+
+       . = _start + 0x200 - PUPA_BOOT_MACHINE_LIST_SIZE
+       
+        /* fill the first data listing with the default */
+blocklist_default_start:
+       /* this is the sector start parameter, in logical sectors from
+          the start of the disk, sector 0 */
+       .long 2
+blocklist_default_len:
+       /* this is the number of sectors to read the command "install"
+          will fill this up */
+       .word 0
+blocklist_default_seg:
+       /* this is the segment of the starting address to load the data into */
+       .word (PUPA_BOOT_MACHINE_KERNEL_SEG + 0x20)
+       
+firstlist:     /* this label has to be after the list data!!! */
diff --git a/conf/i386-pc.mk b/conf/i386-pc.mk
new file mode 100644 (file)
index 0000000..ee4880b
--- /dev/null
@@ -0,0 +1,379 @@
+# -*- makefile -*-
+
+COMMON_ASFLAGS = -nostdinc -fno-builtin
+COMMON_CFLAGS = -fno-builtin
+
+# Images.
+pkgdata_IMAGES = boot.img diskboot.img kernel.img
+
+# For boot.img.
+boot_img_SOURCES = boot/i386/pc/boot.S
+CLEANFILES += boot.img boot.exec boot_img-boot_i386_pc_boot.o
+MOSTLYCLEANFILES += boot_img-boot_i386_pc_boot.d
+
+boot.img: boot.exec
+       $(OBJCOPY) -O binary -R .note -R .comment $< $@
+
+boot.exec: boot_img-boot_i386_pc_boot.o
+       $(CC) $(LDFLAGS) $(boot_img_LDFLAGS) -o $@ $^
+
+boot_img-boot_i386_pc_boot.o: boot/i386/pc/boot.S
+       $(CC) -Iboot/i386/pc -I$(srcdir)/boot/i386/pc $(CPPFLAGS) -DASM_FILE=1 $(ASFLAGS) $(boot_img_ASFLAGS) -c -o $@ $<
+
+boot_img-boot_i386_pc_boot.d: boot/i386/pc/boot.S
+       set -e;           $(CC) -Iboot/i386/pc -I$(srcdir)/boot/i386/pc $(CPPFLAGS) -DASM_FILE=1 $(ASFLAGS) $(boot_img_ASFLAGS) -M $<     | sed 's,boot\.o[ :]*,boot_img-boot_i386_pc_boot.o $@ : ,g' > $@;       [ -s $@ ] || rm -f $@
+
+-include boot_img-boot_i386_pc_boot.d
+
+boot_img_ASFLAGS = $(COMMON_ASFLAGS)
+boot_img_LDFLAGS = -nostdlib -Wl,-N,-Ttext,7C00
+
+# For diskboot.img.
+diskboot_img_SOURCES = boot/i386/pc/diskboot.S
+CLEANFILES += diskboot.img diskboot.exec diskboot_img-boot_i386_pc_diskboot.o
+MOSTLYCLEANFILES += diskboot_img-boot_i386_pc_diskboot.d
+
+diskboot.img: diskboot.exec
+       $(OBJCOPY) -O binary -R .note -R .comment $< $@
+
+diskboot.exec: diskboot_img-boot_i386_pc_diskboot.o
+       $(CC) $(LDFLAGS) $(diskboot_img_LDFLAGS) -o $@ $^
+
+diskboot_img-boot_i386_pc_diskboot.o: boot/i386/pc/diskboot.S
+       $(CC) -Iboot/i386/pc -I$(srcdir)/boot/i386/pc $(CPPFLAGS) -DASM_FILE=1 $(ASFLAGS) $(diskboot_img_ASFLAGS) -c -o $@ $<
+
+diskboot_img-boot_i386_pc_diskboot.d: boot/i386/pc/diskboot.S
+       set -e;           $(CC) -Iboot/i386/pc -I$(srcdir)/boot/i386/pc $(CPPFLAGS) -DASM_FILE=1 $(ASFLAGS) $(diskboot_img_ASFLAGS) -M $<         | sed 's,diskboot\.o[ :]*,diskboot_img-boot_i386_pc_diskboot.o $@ : ,g' > $@;           [ -s $@ ] || rm -f $@
+
+-include diskboot_img-boot_i386_pc_diskboot.d
+
+diskboot_img_ASFLAGS = $(COMMON_ASFLAGS)
+diskboot_img_LDFLAGS = -nostdlib -Wl,-N,-Ttext,8000
+
+# For kernel.img.
+kernel_img_SOURCES = kern/i386/pc/startup.S kern/main.c kern/device.c \
+       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
+       kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
+       kern/i386/dl.c kern/i386/pc/init.c disk/i386/pc/partition.c \
+       disk/i386/pc/biosdisk.c \
+       term/i386/pc/console.c \
+       symlist.c
+CLEANFILES += kernel.img kernel.exec kernel_img-kern_i386_pc_startup.o kernel_img-kern_main.o kernel_img-kern_device.o kernel_img-kern_disk.o kernel_img-kern_dl.o kernel_img-kern_file.o kernel_img-kern_fs.o kernel_img-kern_err.o kernel_img-kern_misc.o kernel_img-kern_mm.o kernel_img-kern_loader.o kernel_img-kern_rescue.o kernel_img-kern_term.o kernel_img-kern_i386_dl.o kernel_img-kern_i386_pc_init.o kernel_img-disk_i386_pc_partition.o kernel_img-disk_i386_pc_biosdisk.o kernel_img-term_i386_pc_console.o kernel_img-symlist.o
+MOSTLYCLEANFILES += kernel_img-kern_i386_pc_startup.d kernel_img-kern_main.d kernel_img-kern_device.d kernel_img-kern_disk.d kernel_img-kern_dl.d kernel_img-kern_file.d kernel_img-kern_fs.d kernel_img-kern_err.d kernel_img-kern_misc.d kernel_img-kern_mm.d kernel_img-kern_loader.d kernel_img-kern_rescue.d kernel_img-kern_term.d kernel_img-kern_i386_dl.d kernel_img-kern_i386_pc_init.d kernel_img-disk_i386_pc_partition.d kernel_img-disk_i386_pc_biosdisk.d kernel_img-term_i386_pc_console.d kernel_img-symlist.d
+
+kernel.img: kernel.exec
+       $(OBJCOPY) -O binary -R .note -R .comment $< $@
+
+kernel.exec: kernel_img-kern_i386_pc_startup.o kernel_img-kern_main.o kernel_img-kern_device.o kernel_img-kern_disk.o kernel_img-kern_dl.o kernel_img-kern_file.o kernel_img-kern_fs.o kernel_img-kern_err.o kernel_img-kern_misc.o kernel_img-kern_mm.o kernel_img-kern_loader.o kernel_img-kern_rescue.o kernel_img-kern_term.o kernel_img-kern_i386_dl.o kernel_img-kern_i386_pc_init.o kernel_img-disk_i386_pc_partition.o kernel_img-disk_i386_pc_biosdisk.o kernel_img-term_i386_pc_console.o kernel_img-symlist.o
+       $(CC) $(LDFLAGS) $(kernel_img_LDFLAGS) -o $@ $^
+
+kernel_img-kern_i386_pc_startup.o: kern/i386/pc/startup.S
+       $(CC) -Ikern/i386/pc -I$(srcdir)/kern/i386/pc $(CPPFLAGS) -DASM_FILE=1 $(ASFLAGS) $(kernel_img_ASFLAGS) -c -o $@ $<
+
+kernel_img-kern_i386_pc_startup.d: kern/i386/pc/startup.S
+       set -e;           $(CC) -Ikern/i386/pc -I$(srcdir)/kern/i386/pc $(CPPFLAGS) -DASM_FILE=1 $(ASFLAGS) $(kernel_img_ASFLAGS) -M $<           | sed 's,startup\.o[ :]*,kernel_img-kern_i386_pc_startup.o $@ : ,g' > $@;       [ -s $@ ] || rm -f $@
+
+-include kernel_img-kern_i386_pc_startup.d
+
+kernel_img-kern_main.o: kern/main.c
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $<
+
+kernel_img-kern_main.d: kern/main.c
+       set -e;           $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -M $<         | sed 's,main\.o[ :]*,kernel_img-kern_main.o $@ : ,g' > $@;     [ -s $@ ] || rm -f $@
+
+-include kernel_img-kern_main.d
+
+kernel_img-kern_device.o: kern/device.c
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $<
+
+kernel_img-kern_device.d: kern/device.c
+       set -e;           $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -M $<         | sed 's,device\.o[ :]*,kernel_img-kern_device.o $@ : ,g' > $@;         [ -s $@ ] || rm -f $@
+
+-include kernel_img-kern_device.d
+
+kernel_img-kern_disk.o: kern/disk.c
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $<
+
+kernel_img-kern_disk.d: kern/disk.c
+       set -e;           $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -M $<         | sed 's,disk\.o[ :]*,kernel_img-kern_disk.o $@ : ,g' > $@;     [ -s $@ ] || rm -f $@
+
+-include kernel_img-kern_disk.d
+
+kernel_img-kern_dl.o: kern/dl.c
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $<
+
+kernel_img-kern_dl.d: kern/dl.c
+       set -e;           $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -M $<         | sed 's,dl\.o[ :]*,kernel_img-kern_dl.o $@ : ,g' > $@;         [ -s $@ ] || rm -f $@
+
+-include kernel_img-kern_dl.d
+
+kernel_img-kern_file.o: kern/file.c
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $<
+
+kernel_img-kern_file.d: kern/file.c
+       set -e;           $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -M $<         | sed 's,file\.o[ :]*,kernel_img-kern_file.o $@ : ,g' > $@;     [ -s $@ ] || rm -f $@
+
+-include kernel_img-kern_file.d
+
+kernel_img-kern_fs.o: kern/fs.c
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $<
+
+kernel_img-kern_fs.d: kern/fs.c
+       set -e;           $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -M $<         | sed 's,fs\.o[ :]*,kernel_img-kern_fs.o $@ : ,g' > $@;         [ -s $@ ] || rm -f $@
+
+-include kernel_img-kern_fs.d
+
+kernel_img-kern_err.o: kern/err.c
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $<
+
+kernel_img-kern_err.d: kern/err.c
+       set -e;           $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -M $<         | sed 's,err\.o[ :]*,kernel_img-kern_err.o $@ : ,g' > $@;       [ -s $@ ] || rm -f $@
+
+-include kernel_img-kern_err.d
+
+kernel_img-kern_misc.o: kern/misc.c
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $<
+
+kernel_img-kern_misc.d: kern/misc.c
+       set -e;           $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -M $<         | sed 's,misc\.o[ :]*,kernel_img-kern_misc.o $@ : ,g' > $@;     [ -s $@ ] || rm -f $@
+
+-include kernel_img-kern_misc.d
+
+kernel_img-kern_mm.o: kern/mm.c
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $<
+
+kernel_img-kern_mm.d: kern/mm.c
+       set -e;           $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -M $<         | sed 's,mm\.o[ :]*,kernel_img-kern_mm.o $@ : ,g' > $@;         [ -s $@ ] || rm -f $@
+
+-include kernel_img-kern_mm.d
+
+kernel_img-kern_loader.o: kern/loader.c
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $<
+
+kernel_img-kern_loader.d: kern/loader.c
+       set -e;           $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -M $<         | sed 's,loader\.o[ :]*,kernel_img-kern_loader.o $@ : ,g' > $@;         [ -s $@ ] || rm -f $@
+
+-include kernel_img-kern_loader.d
+
+kernel_img-kern_rescue.o: kern/rescue.c
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $<
+
+kernel_img-kern_rescue.d: kern/rescue.c
+       set -e;           $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -M $<         | sed 's,rescue\.o[ :]*,kernel_img-kern_rescue.o $@ : ,g' > $@;         [ -s $@ ] || rm -f $@
+
+-include kernel_img-kern_rescue.d
+
+kernel_img-kern_term.o: kern/term.c
+       $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $<
+
+kernel_img-kern_term.d: kern/term.c
+       set -e;           $(CC) -Ikern -I$(srcdir)/kern $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -M $<         | sed 's,term\.o[ :]*,kernel_img-kern_term.o $@ : ,g' > $@;     [ -s $@ ] || rm -f $@
+
+-include kernel_img-kern_term.d
+
+kernel_img-kern_i386_dl.o: kern/i386/dl.c
+       $(CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $<
+
+kernel_img-kern_i386_dl.d: kern/i386/dl.c
+       set -e;           $(CC) -Ikern/i386 -I$(srcdir)/kern/i386 $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -M $<       | sed 's,dl\.o[ :]*,kernel_img-kern_i386_dl.o $@ : ,g' > $@;    [ -s $@ ] || rm -f $@
+
+-include kernel_img-kern_i386_dl.d
+
+kernel_img-kern_i386_pc_init.o: kern/i386/pc/init.c
+       $(CC) -Ikern/i386/pc -I$(srcdir)/kern/i386/pc $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $<
+
+kernel_img-kern_i386_pc_init.d: kern/i386/pc/init.c
+       set -e;           $(CC) -Ikern/i386/pc -I$(srcdir)/kern/i386/pc $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -M $<         | sed 's,init\.o[ :]*,kernel_img-kern_i386_pc_init.o $@ : ,g' > $@;     [ -s $@ ] || rm -f $@
+
+-include kernel_img-kern_i386_pc_init.d
+
+kernel_img-disk_i386_pc_partition.o: disk/i386/pc/partition.c
+       $(CC) -Idisk/i386/pc -I$(srcdir)/disk/i386/pc $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $<
+
+kernel_img-disk_i386_pc_partition.d: disk/i386/pc/partition.c
+       set -e;           $(CC) -Idisk/i386/pc -I$(srcdir)/disk/i386/pc $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -M $<         | sed 's,partition\.o[ :]*,kernel_img-disk_i386_pc_partition.o $@ : ,g' > $@;           [ -s $@ ] || rm -f $@
+
+-include kernel_img-disk_i386_pc_partition.d
+
+kernel_img-disk_i386_pc_biosdisk.o: disk/i386/pc/biosdisk.c
+       $(CC) -Idisk/i386/pc -I$(srcdir)/disk/i386/pc $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $<
+
+kernel_img-disk_i386_pc_biosdisk.d: disk/i386/pc/biosdisk.c
+       set -e;           $(CC) -Idisk/i386/pc -I$(srcdir)/disk/i386/pc $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -M $<         | sed 's,biosdisk\.o[ :]*,kernel_img-disk_i386_pc_biosdisk.o $@ : ,g' > $@;     [ -s $@ ] || rm -f $@
+
+-include kernel_img-disk_i386_pc_biosdisk.d
+
+kernel_img-term_i386_pc_console.o: term/i386/pc/console.c
+       $(CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $<
+
+kernel_img-term_i386_pc_console.d: term/i386/pc/console.c
+       set -e;           $(CC) -Iterm/i386/pc -I$(srcdir)/term/i386/pc $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -M $<         | sed 's,console\.o[ :]*,kernel_img-term_i386_pc_console.o $@ : ,g' > $@;       [ -s $@ ] || rm -f $@
+
+-include kernel_img-term_i386_pc_console.d
+
+kernel_img-symlist.o: symlist.c
+       $(CC) -I. -I$(srcdir)/. $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -c -o $@ $<
+
+kernel_img-symlist.d: symlist.c
+       set -e;           $(CC) -I. -I$(srcdir)/. $(CPPFLAGS)  $(CFLAGS) $(kernel_img_CFLAGS) -M $<       | sed 's,symlist\.o[ :]*,kernel_img-symlist.o $@ : ,g' > $@;    [ -s $@ ] || rm -f $@
+
+-include kernel_img-symlist.d
+
+kernel_img_HEADERS = boot.h device.h disk.h dl.h elf.h err.h \
+       file.h fs.h kernel.h loader.h misc.h mm.h net.h rescue.h symbol.h \
+       term.h types.h machine/biosdisk.h machine/boot.h \
+       machine/console.h machine/init.h machine/memory.h \
+       machine/loader.h machine/partition.h
+kernel_img_CFLAGS = $(COMMON_CFLAGS)
+kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
+kernel_img_LDFLAGS = -nostdlib -Wl,-N,-Ttext,8200
+
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+symlist.c: $(addprefix include/pupa/,$(kernel_img_HEADERS)) gensymlist.sh
+       sh $(srcdir)/gensymlist.sh $(filter %.h,$^) > $@
+
+kernel_syms.lst: $(addprefix include/pupa/,$(kernel_img_HEADERS)) genkernsyms.sh
+       sh $(srcdir)/genkernsyms.sh $(filter %h,$^) > $@
+
+# Utilities.
+bin_UTILITIES = pupa-mkimage
+noinst_UTILITIES = genmoddep
+
+# For pupa-mkimage.
+pupa_mkimage_SOURCES = util/i386/pc/pupa-mkimage.c util/misc.c \
+       util/resolve.c
+CLEANFILES += pupa-mkimage pupa_mkimage-util_i386_pc_pupa_mkimage.o pupa_mkimage-util_misc.o pupa_mkimage-util_resolve.o
+MOSTLYCLEANFILES += pupa_mkimage-util_i386_pc_pupa_mkimage.d pupa_mkimage-util_misc.d pupa_mkimage-util_resolve.d
+
+pupa-mkimage: pupa_mkimage-util_i386_pc_pupa_mkimage.o pupa_mkimage-util_misc.o pupa_mkimage-util_resolve.o
+       $(BUILD_CC) $(BUILD_LDFLAGS) $(pupa_mkimage_LDFLAGS) -o $@ $^
+
+pupa_mkimage-util_i386_pc_pupa_mkimage.o: util/i386/pc/pupa-mkimage.c
+       $(BUILD_CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -c -o $@ $<
+
+pupa_mkimage-util_i386_pc_pupa_mkimage.d: util/i386/pc/pupa-mkimage.c
+       set -e;           $(BUILD_CC) -Iutil/i386/pc -I$(srcdir)/util/i386/pc $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -M $<        | sed 's,pupa\-mkimage\.o[ :]*,pupa_mkimage-util_i386_pc_pupa_mkimage.o $@ : ,g' > $@;          [ -s $@ ] || rm -f $@
+
+-include pupa_mkimage-util_i386_pc_pupa_mkimage.d
+
+pupa_mkimage-util_misc.o: util/misc.c
+       $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -c -o $@ $<
+
+pupa_mkimage-util_misc.d: util/misc.c
+       set -e;           $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -M $<        | sed 's,misc\.o[ :]*,pupa_mkimage-util_misc.o $@ : ,g' > $@;           [ -s $@ ] || rm -f $@
+
+-include pupa_mkimage-util_misc.d
+
+pupa_mkimage-util_resolve.o: util/resolve.c
+       $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -c -o $@ $<
+
+pupa_mkimage-util_resolve.d: util/resolve.c
+       set -e;           $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(pupa_mkimage_CFLAGS) -M $<        | sed 's,resolve\.o[ :]*,pupa_mkimage-util_resolve.o $@ : ,g' > $@;     [ -s $@ ] || rm -f $@
+
+-include pupa_mkimage-util_resolve.d
+
+
+# For genmoddep.
+genmoddep_SOURCES = util/genmoddep.c
+CLEANFILES += genmoddep genmoddep-util_genmoddep.o
+MOSTLYCLEANFILES += genmoddep-util_genmoddep.d
+
+genmoddep: genmoddep-util_genmoddep.o
+       $(BUILD_CC) $(BUILD_LDFLAGS) $(genmoddep_LDFLAGS) -o $@ $^
+
+genmoddep-util_genmoddep.o: util/genmoddep.c
+       $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(genmoddep_CFLAGS) -c -o $@ $<
+
+genmoddep-util_genmoddep.d: util/genmoddep.c
+       set -e;           $(BUILD_CC) -Iutil -I$(srcdir)/util $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(genmoddep_CFLAGS) -M $<           | sed 's,genmoddep\.o[ :]*,genmoddep-util_genmoddep.o $@ : ,g' > $@;    [ -s $@ ] || rm -f $@
+
+-include genmoddep-util_genmoddep.d
+
+
+# Modules.
+pkgdata_MODULES = chain.mod fat.mod
+
+# For chain.mod.
+chain_mod_SOURCES = loader/i386/pc/chainloader.c
+CLEANFILES += chain.mod mod-chain.o mod-chain.c pre-chain.o chain_mod-loader_i386_pc_chainloader.o def-chain.lst und-chain.lst
+MOSTLYCLEANFILES += chain_mod-loader_i386_pc_chainloader.d
+DEFSYMFILES += def-chain.lst
+UNDSYMFILES += und-chain.lst
+
+chain.mod: pre-chain.o mod-chain.o
+       -rm -f $@
+       $(LD) -r -o $@ $^
+       $(STRIP) --strip-unneeded -K pupa_mod_init -K pupa_mod_fini -R .note -R .comment $@
+
+pre-chain.o: chain_mod-loader_i386_pc_chainloader.o
+       -rm -f $@
+       $(LD) -r -o $@ $^
+
+mod-chain.o: mod-chain.c
+       $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
+
+mod-chain.c: moddep.lst genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'chain' $< > $@ || (rm -f $@; exit 1)
+
+def-chain.lst: pre-chain.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 chain/' > $@
+
+und-chain.lst: pre-chain.o
+       echo 'chain' > $@
+       $(NM) -u -P -p $< >> $@
+
+chain_mod-loader_i386_pc_chainloader.o: loader/i386/pc/chainloader.c
+       $(CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(CPPFLAGS) $(CFLAGS) $(chain_mod_CFLAGS) -c -o $@ $<
+
+chain_mod-loader_i386_pc_chainloader.d: loader/i386/pc/chainloader.c
+       set -e;           $(CC) -Iloader/i386/pc -I$(srcdir)/loader/i386/pc $(CPPFLAGS) $(CFLAGS) $(chain_mod_CFLAGS) -M $<       | sed 's,chainloader\.o[ :]*,chain_mod-loader_i386_pc_chainloader.o $@ : ,g' > $@;      [ -s $@ ] || rm -f $@
+
+-include chain_mod-loader_i386_pc_chainloader.d
+
+chain_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For fat.mod.
+fat_mod_SOURCES = fs/fat.c
+CLEANFILES += fat.mod mod-fat.o mod-fat.c pre-fat.o fat_mod-fs_fat.o def-fat.lst und-fat.lst
+MOSTLYCLEANFILES += fat_mod-fs_fat.d
+DEFSYMFILES += def-fat.lst
+UNDSYMFILES += und-fat.lst
+
+fat.mod: pre-fat.o mod-fat.o
+       -rm -f $@
+       $(LD) -r -o $@ $^
+       $(STRIP) --strip-unneeded -K pupa_mod_init -K pupa_mod_fini -R .note -R .comment $@
+
+pre-fat.o: fat_mod-fs_fat.o
+       -rm -f $@
+       $(LD) -r -o $@ $^
+
+mod-fat.o: mod-fat.c
+       $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
+
+mod-fat.c: moddep.lst genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh 'fat' $< > $@ || (rm -f $@; exit 1)
+
+def-fat.lst: pre-fat.o
+       $(NM) -g --defined-only -P -p $< | sed 's/^\([^ ]*\).*/\1 fat/' > $@
+
+und-fat.lst: pre-fat.o
+       echo 'fat' > $@
+       $(NM) -u -P -p $< >> $@
+
+fat_mod-fs_fat.o: fs/fat.c
+       $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) $(fat_mod_CFLAGS) -c -o $@ $<
+
+fat_mod-fs_fat.d: fs/fat.c
+       set -e;           $(CC) -Ifs -I$(srcdir)/fs $(CPPFLAGS) $(CFLAGS) $(fat_mod_CFLAGS) -M $<         | sed 's,fat\.o[ :]*,fat_mod-fs_fat.o $@ : ,g' > $@;    [ -s $@ ] || rm -f $@
+
+-include fat_mod-fs_fat.d
+
+fat_mod_CFLAGS = $(COMMON_CFLAGS)
+CLEANFILES += moddep.lst
+pkgdata_DATA += moddep.lst
+moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep
+       cat $(DEFSYMFILES) /dev/null | ./genmoddep $(UNDSYMFILES) > $@ \
+         || (rm -f $@; exit 1)
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
new file mode 100644 (file)
index 0000000..9f72c7e
--- /dev/null
@@ -0,0 +1,65 @@
+# -*- makefile -*-
+
+COMMON_ASFLAGS = -nostdinc -fno-builtin
+COMMON_CFLAGS = -fno-builtin
+
+# Images.
+pkgdata_IMAGES = boot.img diskboot.img kernel.img
+
+# For boot.img.
+boot_img_SOURCES = boot/i386/pc/boot.S
+boot_img_ASFLAGS = $(COMMON_ASFLAGS)
+boot_img_LDFLAGS = -nostdlib -Wl,-N,-Ttext,7C00
+
+# For diskboot.img.
+diskboot_img_SOURCES = boot/i386/pc/diskboot.S
+diskboot_img_ASFLAGS = $(COMMON_ASFLAGS)
+diskboot_img_LDFLAGS = -nostdlib -Wl,-N,-Ttext,8000
+
+# For kernel.img.
+kernel_img_SOURCES = kern/i386/pc/startup.S kern/main.c kern/device.c \
+       kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
+       kern/misc.c kern/mm.c kern/loader.c kern/rescue.c kern/term.c \
+       kern/i386/dl.c kern/i386/pc/init.c disk/i386/pc/partition.c \
+       disk/i386/pc/biosdisk.c \
+       term/i386/pc/console.c \
+       symlist.c
+kernel_img_HEADERS = boot.h device.h disk.h dl.h elf.h err.h \
+       file.h fs.h kernel.h loader.h misc.h mm.h net.h rescue.h symbol.h \
+       term.h types.h machine/biosdisk.h machine/boot.h \
+       machine/console.h machine/init.h machine/memory.h \
+       machine/loader.h machine/partition.h
+kernel_img_CFLAGS = $(COMMON_CFLAGS)
+kernel_img_ASFLAGS = $(COMMON_ASFLAGS)
+kernel_img_LDFLAGS = -nostdlib -Wl,-N,-Ttext,8200
+
+MOSTLYCLEANFILES += symlist.c kernel_syms.lst
+DEFSYMFILES += kernel_syms.lst
+
+symlist.c: $(addprefix include/pupa/,$(kernel_img_HEADERS)) gensymlist.sh
+       sh $(srcdir)/gensymlist.sh $(filter %.h,$^) > $@
+
+kernel_syms.lst: $(addprefix include/pupa/,$(kernel_img_HEADERS)) genkernsyms.sh
+       sh $(srcdir)/genkernsyms.sh $(filter %h,$^) > $@
+
+# Utilities.
+bin_UTILITIES = pupa-mkimage
+noinst_UTILITIES = genmoddep
+
+# For pupa-mkimage.
+pupa_mkimage_SOURCES = util/i386/pc/pupa-mkimage.c util/misc.c \
+       util/resolve.c
+
+# For genmoddep.
+genmoddep_SOURCES = util/genmoddep.c
+
+# Modules.
+pkgdata_MODULES = chain.mod fat.mod
+
+# For chain.mod.
+chain_mod_SOURCES = loader/i386/pc/chainloader.c
+chain_mod_CFLAGS = $(COMMON_CFLAGS)
+
+# For fat.mod.
+fat_mod_SOURCES = fs/fat.c
+fat_mod_CFLAGS = $(COMMON_CFLAGS)
diff --git a/config.guess b/config.guess
new file mode 100644 (file)
index 0000000..ed2e03b
--- /dev/null
@@ -0,0 +1,1321 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002 Free Software Foundation, Inc.
+
+timestamp='2002-03-20'
+
+# 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+
+dummy=dummy-$$
+trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script.
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int dummy(){}" > $dummy.c ;
+       for c in cc gcc c89 c99 ; do
+         ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ;
+         if test $? = 0 ; then
+            CC_FOR_BUILD="$c"; break ;
+         fi ;
+       done ;
+       rm -f $dummy.c $dummy.o $dummy.rel ;
+       if test x"$CC_FOR_BUILD" = x ; then
+         CC_FOR_BUILD=no_compiler_found ;
+       fi
+       ;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+       PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+       # NetBSD (nbsd) targets should (where applicable) match one or
+       # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+       # *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+       # switched to ELF, *-*-netbsd* would select the old
+       # object file format.  This provides both forward
+       # compatibility and a consistent mechanism for selecting the
+       # object file format.
+       #
+       # Note: NetBSD doesn't particularly care about the vendor
+       # portion of the name.  We always set it to "unknown".
+       sysctl="sysctl -n hw.machine_arch"
+       UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+           /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+       case "${UNAME_MACHINE_ARCH}" in
+           arm*) machine=arm-unknown ;;
+           sh3el) machine=shl-unknown ;;
+           sh3eb) machine=sh-unknown ;;
+           *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+       esac
+       # The Operating System including object format, if it has switched
+       # to ELF recently, or will in the future.
+       case "${UNAME_MACHINE_ARCH}" in
+           arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+               eval $set_cc_for_build
+               if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+                       | grep __ELF__ >/dev/null
+               then
+                   # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+                   # Return netbsd for either.  FIX?
+                   os=netbsd
+               else
+                   os=netbsdelf
+               fi
+               ;;
+           *)
+               os=netbsd
+               ;;
+       esac
+       # The OS release
+       release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+       # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+       # contains redundant information, the shorter form:
+       # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+       echo "${machine}-${os}${release}"
+       exit 0 ;;
+    amiga:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    arc:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    hp300:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mac68k:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    macppc:OpenBSD:*:*)
+       echo powerpc-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvme68k:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvme88k:OpenBSD:*:*)
+       echo m88k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvmeppc:OpenBSD:*:*)
+       echo powerpc-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    pmax:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    sgi:OpenBSD:*:*)
+       echo mipseb-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    sun3:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    wgrisc:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    *:OpenBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    alpha:OSF1:*:*)
+       if test $UNAME_RELEASE = "V4.0"; then
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+       fi
+       # A Vn.n version is a released version.
+       # A Tn.n version is a released field test version.
+       # A Xn.n version is an unreleased experimental baselevel.
+       # 1.2 uses "1.2" for uname -r.
+       cat <<EOF >$dummy.s
+       .data
+\$Lformat:
+       .byte 37,100,45,37,120,10,0     # "%d-%x\n"
+
+       .text
+       .globl main
+       .align 4
+       .ent main
+main:
+       .frame \$30,16,\$26,0
+       ldgp \$29,0(\$27)
+       .prologue 1
+       .long 0x47e03d80 # implver \$0
+       lda \$2,-1
+       .long 0x47e20c21 # amask \$2,\$1
+       lda \$16,\$Lformat
+       mov \$0,\$17
+       not \$1,\$18
+       jsr \$26,printf
+       ldgp \$29,0(\$26)
+       mov 0,\$16
+       jsr \$26,exit
+       .end main
+EOF
+       eval $set_cc_for_build
+       $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
+       if test "$?" = 0 ; then
+               case `./$dummy` in
+                       0-0)
+                               UNAME_MACHINE="alpha"
+                               ;;
+                       1-0)
+                               UNAME_MACHINE="alphaev5"
+                               ;;
+                       1-1)
+                               UNAME_MACHINE="alphaev56"
+                               ;;
+                       1-101)
+                               UNAME_MACHINE="alphapca56"
+                               ;;
+                       2-303)
+                               UNAME_MACHINE="alphaev6"
+                               ;;
+                       2-307)
+                               UNAME_MACHINE="alphaev67"
+                               ;;
+                       2-1307)
+                               UNAME_MACHINE="alphaev68"
+                               ;;
+               esac
+       fi
+       rm -f $dummy.s $dummy
+       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+       exit 0 ;;
+    Alpha\ *:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # Should we change UNAME_MACHINE based on the output of uname instead
+       # of the specific Alpha model?
+       echo alpha-pc-interix
+       exit 0 ;;
+    21064:Windows_NT:50:3)
+       echo alpha-dec-winnt3.5
+       exit 0 ;;
+    Amiga*:UNIX_System_V:4.0:*)
+       echo m68k-unknown-sysv4
+       exit 0;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-amigaos
+       exit 0 ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-morphos
+       exit 0 ;;
+    *:OS/390:*:*)
+       echo i370-ibm-openedition
+       exit 0 ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+       echo arm-acorn-riscix${UNAME_RELEASE}
+       exit 0;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+       echo hppa1.1-hitachi-hiuxmpp
+       exit 0;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+       # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+       if test "`(/bin/universe) 2>/dev/null`" = att ; then
+               echo pyramid-pyramid-sysv3
+       else
+               echo pyramid-pyramid-bsd
+       fi
+       exit 0 ;;
+    NILE*:*:*:dcosx)
+       echo pyramid-pyramid-svr4
+       exit 0 ;;
+    sun4H:SunOS:5.*:*)
+       echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+       echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    i86pc:SunOS:5.*:*)
+       echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    sun4*:SunOS:6*:*)
+       # According to config.sub, this is the proper way to canonicalize
+       # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+       # it's likely to be more like Solaris than SunOS4.
+       echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    sun4*:SunOS:*:*)
+       case "`/usr/bin/arch -k`" in
+           Series*|S4*)
+               UNAME_RELEASE=`uname -v`
+               ;;
+       esac
+       # Japanese Language versions have a version number like `4.1.3-JL'.
+       echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+       exit 0 ;;
+    sun3*:SunOS:*:*)
+       echo m68k-sun-sunos${UNAME_RELEASE}
+       exit 0 ;;
+    sun*:*:4.2BSD:*)
+       UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+       test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+       case "`/bin/arch`" in
+           sun3)
+               echo m68k-sun-sunos${UNAME_RELEASE}
+               ;;
+           sun4)
+               echo sparc-sun-sunos${UNAME_RELEASE}
+               ;;
+       esac
+       exit 0 ;;
+    aushp:SunOS:*:*)
+       echo sparc-auspex-sunos${UNAME_RELEASE}
+       exit 0 ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit 0 ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+       echo m68k-atari-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit 0 ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit 0 ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit 0 ;;
+    powerpc:machten:*:*)
+       echo powerpc-apple-machten${UNAME_RELEASE}
+       exit 0 ;;
+    RISC*:Mach:*:*)
+       echo mips-dec-mach_bsd4.3
+       exit 0 ;;
+    RISC*:ULTRIX:*:*)
+       echo mips-dec-ultrix${UNAME_RELEASE}
+       exit 0 ;;
+    VAX*:ULTRIX*:*:*)
+       echo vax-dec-ultrix${UNAME_RELEASE}
+       exit 0 ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+       echo clipper-intergraph-clix${UNAME_RELEASE}
+       exit 0 ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+       int main (int argc, char *argv[]) {
+#else
+       int main (argc, argv) int argc; char *argv[]; {
+#endif
+       #if defined (host_mips) && defined (MIPSEB)
+       #if defined (SYSTYPE_SYSV)
+         printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_SVR4)
+         printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+         printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+       #endif
+       #endif
+         exit (-1);
+       }
+EOF
+       $CC_FOR_BUILD $dummy.c -o $dummy \
+         && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+         && rm -f $dummy.c $dummy && exit 0
+       rm -f $dummy.c $dummy
+       echo mips-mips-riscos${UNAME_RELEASE}
+       exit 0 ;;
+    Motorola:PowerMAX_OS:*:*)
+       echo powerpc-motorola-powermax
+       exit 0 ;;
+    Night_Hawk:Power_UNIX:*:*)
+       echo powerpc-harris-powerunix
+       exit 0 ;;
+    m88k:CX/UX:7*:*)
+       echo m88k-harris-cxux7
+       exit 0 ;;
+    m88k:*:4*:R4*)
+       echo m88k-motorola-sysv4
+       exit 0 ;;
+    m88k:*:3*:R3*)
+       echo m88k-motorola-sysv3
+       exit 0 ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+       if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+       then
+           if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+              [ ${TARGET_BINARY_INTERFACE}x = x ]
+           then
+               echo m88k-dg-dgux${UNAME_RELEASE}
+           else
+               echo m88k-dg-dguxbcs${UNAME_RELEASE}
+           fi
+       else
+           echo i586-dg-dgux${UNAME_RELEASE}
+       fi
+       exit 0 ;;
+    M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
+       echo m88k-dolphin-sysv3
+       exit 0 ;;
+    M88*:*:R3*:*)
+       # Delta 88k system running SVR3
+       echo m88k-motorola-sysv3
+       exit 0 ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+       echo m88k-tektronix-sysv3
+       exit 0 ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+       echo m68k-tektronix-bsd
+       exit 0 ;;
+    *:IRIX*:*:*)
+       echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+       exit 0 ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+       echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
+       exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+       echo i386-ibm-aix
+       exit 0 ;;
+    ia64:AIX:*:*)
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+       exit 0 ;;
+    *:AIX:2:3)
+       if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+               eval $set_cc_for_build
+               sed 's/^                //' << EOF >$dummy.c
+               #include <sys/systemcfg.h>
+
+               main()
+                       {
+                       if (!__power_pc())
+                               exit(1);
+                       puts("powerpc-ibm-aix3.2.5");
+                       exit(0);
+                       }
+EOF
+               $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+               rm -f $dummy.c $dummy
+               echo rs6000-ibm-aix3.2.5
+       elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+               echo rs6000-ibm-aix3.2.4
+       else
+               echo rs6000-ibm-aix3.2
+       fi
+       exit 0 ;;
+    *:AIX:*:[45])
+       IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+       if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+               IBM_ARCH=rs6000
+       else
+               IBM_ARCH=powerpc
+       fi
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+       exit 0 ;;
+    *:AIX:*:*)
+       echo rs6000-ibm-aix
+       exit 0 ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+       echo romp-ibm-bsd4.4
+       exit 0 ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+       echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+       exit 0 ;;                           # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+       echo rs6000-bull-bosx
+       exit 0 ;;
+    DPX/2?00:B.O.S.:*:*)
+       echo m68k-bull-sysv3
+       exit 0 ;;
+    9000/[34]??:4.3bsd:1.*:*)
+       echo m68k-hp-bsd
+       exit 0 ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+       echo m68k-hp-bsd4.4
+       exit 0 ;;
+    9000/[34678]??:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       case "${UNAME_MACHINE}" in
+           9000/31? )            HP_ARCH=m68000 ;;
+           9000/[34]?? )         HP_ARCH=m68k ;;
+           9000/[678][0-9][0-9])
+               if [ -x /usr/bin/getconf ]; then
+                   sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+                         '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+               fi
+               if [ "${HP_ARCH}" = "" ]; then
+                   eval $set_cc_for_build
+                   sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+               {
+               case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+               case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+               case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+                   switch (bits)
+                       {
+                       case 64: puts ("hppa2.0w"); break;
+                       case 32: puts ("hppa2.0n"); break;
+                       default: puts ("hppa2.0"); break;
+                       } break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+                   puts ("hppa2.0"); break;
+              #endif
+               default: puts ("hppa1.0"); break;
+               }
+                  exit (0);
+              }
+EOF
+                   (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy`
+                   if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
+                   rm -f $dummy.c $dummy
+               fi ;;
+       esac
+       echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+       exit 0 ;;
+    ia64:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       echo ia64-hp-hpux${HPUX_REV}
+       exit 0 ;;
+    3050*:HI-UX:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <unistd.h>
+       int
+       main ()
+       {
+         long cpu = sysconf (_SC_CPU_VERSION);
+         /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+            true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+            results, however.  */
+         if (CPU_IS_PA_RISC (cpu))
+           {
+             switch (cpu)
+               {
+                 case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+                 default: puts ("hppa-hitachi-hiuxwe2"); break;
+               }
+           }
+         else if (CPU_IS_HP_MC68K (cpu))
+           puts ("m68k-hitachi-hiuxwe2");
+         else puts ("unknown-hitachi-hiuxwe2");
+         exit (0);
+       }
+EOF
+       $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+       rm -f $dummy.c $dummy
+       echo unknown-hitachi-hiuxwe2
+       exit 0 ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+       echo hppa1.1-hp-bsd
+       exit 0 ;;
+    9000/8??:4.3bsd:*:*)
+       echo hppa1.0-hp-bsd
+       exit 0 ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+       echo hppa1.0-hp-mpeix
+       exit 0 ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+       echo hppa1.1-hp-osf
+       exit 0 ;;
+    hp8??:OSF1:*:*)
+       echo hppa1.0-hp-osf
+       exit 0 ;;
+    i*86:OSF1:*:*)
+       if [ -x /usr/sbin/sysversion ] ; then
+           echo ${UNAME_MACHINE}-unknown-osf1mk
+       else
+           echo ${UNAME_MACHINE}-unknown-osf1
+       fi
+       exit 0 ;;
+    parisc*:Lites*:*:*)
+       echo hppa1.1-hp-lites
+       exit 0 ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+       echo c1-convex-bsd
+        exit 0 ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+        exit 0 ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+       echo c34-convex-bsd
+        exit 0 ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+       echo c38-convex-bsd
+        exit 0 ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+       echo c4-convex-bsd
+        exit 0 ;;
+    CRAY*Y-MP:*:*:*)
+       echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*[A-Z]90:*:*:*)
+       echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+       | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+             -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+             -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*TS:*:*:*)
+       echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*T3D:*:*:*)
+       echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*T3E:*:*:*)
+       echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*SV1:*:*:*)
+       echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+       FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit 0 ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+       echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+       exit 0 ;;
+    sparc*:BSD/OS:*:*)
+       echo sparc-unknown-bsdi${UNAME_RELEASE}
+       exit 0 ;;
+    *:BSD/OS:*:*)
+       echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+       exit 0 ;;
+    *:FreeBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       exit 0 ;;
+    i*:CYGWIN*:*)
+       echo ${UNAME_MACHINE}-pc-cygwin
+       exit 0 ;;
+    i*:MINGW*:*)
+       echo ${UNAME_MACHINE}-pc-mingw32
+       exit 0 ;;
+    i*:PW*:*)
+       echo ${UNAME_MACHINE}-pc-pw32
+       exit 0 ;;
+    x86:Interix*:3*)
+       echo i386-pc-interix3
+       exit 0 ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+       # UNAME_MACHINE based on the output of uname instead of i386?
+       echo i386-pc-interix
+       exit 0 ;;
+    i*:UWIN*:*)
+       echo ${UNAME_MACHINE}-pc-uwin
+       exit 0 ;;
+    p*:CYGWIN*:*)
+       echo powerpcle-unknown-cygwin
+       exit 0 ;;
+    prep*:SunOS:5.*:*)
+       echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    *:GNU:*:*)
+       echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+       exit 0 ;;
+    i*86:Minix:*:*)
+       echo ${UNAME_MACHINE}-pc-minix
+       exit 0 ;;
+    arm*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    ia64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    m68*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    mips:Linux:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #undef CPU
+       #undef mips
+       #undef mipsel
+       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+       CPU=mipsel
+       #else
+       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+       CPU=mips
+       #else
+       CPU=
+       #endif
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+       rm -f $dummy.c
+       test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0
+       ;;
+    ppc:Linux:*:*)
+       echo powerpc-unknown-linux-gnu
+       exit 0 ;;
+    ppc64:Linux:*:*)
+       echo powerpc64-unknown-linux-gnu
+       exit 0 ;;
+    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 ld.so.1 >/dev/null
+       if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+       echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+       exit 0 ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+       # Look for CPU level
+       case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+         PA7*) echo hppa1.1-unknown-linux-gnu ;;
+         PA8*) echo hppa2.0-unknown-linux-gnu ;;
+         *)    echo hppa-unknown-linux-gnu ;;
+       esac
+       exit 0 ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+       echo hppa64-unknown-linux-gnu
+       exit 0 ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+       echo ${UNAME_MACHINE}-ibm-linux
+       exit 0 ;;
+    sh*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    x86_64:Linux:*:*)
+       echo x86_64-unknown-linux-gnu
+       exit 0 ;;
+    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"
+               ;;
+         a.out-i386-linux)
+               echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+               exit 0 ;;               
+         coff-i386)
+               echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+               exit 0 ;;
+         "")
+               # Either a pre-BFD a.out linker (linux-gnuoldld) or
+               # one that does not give us useful --help.
+               echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+               exit 0 ;;
+       esac
+       # Determine whether the default compiler is a.out or elf
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <features.h>
+       #ifdef __ELF__
+       # ifdef __GLIBC__
+       #  if __GLIBC__ >= 2
+       LIBC=gnu
+       #  else
+       LIBC=gnulibc1
+       #  endif
+       # else
+       LIBC=gnulibc1
+       # endif
+       #else
+       #ifdef __INTEL_COMPILER
+       LIBC=gnu
+       #else
+       LIBC=gnuaout
+       #endif
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+       rm -f $dummy.c
+       test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+       test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+       ;;
+    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
+       # sysname and nodename.
+       echo i386-sequent-sysv4
+       exit 0 ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+       # I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+       echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+       exit 0 ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+       UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+       if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+               echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+       else
+               echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+       fi
+       exit 0 ;;
+    i*86:*:5:[78]*)
+       case `/bin/uname -X | grep "^Machine"` in
+           *486*)           UNAME_MACHINE=i486 ;;
+           *Pentium)        UNAME_MACHINE=i586 ;;
+           *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+       esac
+       echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+       exit 0 ;;
+    i*86:*:3.2:*)
+       if test -f /usr/options/cb.name; then
+               UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+               echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+       elif /bin/uname -X 2>/dev/null >/dev/null ; then
+               UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+               (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+               (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+                       && UNAME_MACHINE=i586
+               (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+       else
+               echo ${UNAME_MACHINE}-pc-sysv32
+       fi
+       exit 0 ;;
+    i*86:*DOS:*:*)
+       echo ${UNAME_MACHINE}-pc-msdosdjgpp
+       exit 0 ;;
+    pc:*:*:*)
+       # Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i386.
+       echo i386-pc-msdosdjgpp
+        exit 0 ;;
+    Intel:Mach:3*:*)
+       echo i386-pc-mach3
+       exit 0 ;;
+    paragon:*:*:*)
+       echo i860-intel-osf1
+       exit 0 ;;
+    i860:*:4.*:*) # i860-SVR4
+       if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+         echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+       else # Add other i860-SVR4 vendors below as they are discovered.
+         echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+       fi
+       exit 0 ;;
+    mini*:CTIX:SYS*5:*)
+       # "miniframe"
+       echo m68010-convergent-sysv
+       exit 0 ;;
+    M68*:*:R3V[567]*:*)
+       test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0)
+       OS_REL=''
+       test -r /etc/.relid \
+       && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+         && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+         && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4 && exit 0 ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+       echo m68k-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    mc68030:UNIX_System_V:4.*:*)
+       echo m68k-atari-sysv4
+       exit 0 ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+       echo i386-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    TSUNAMI:LynxOS:2.*:*)
+       echo sparc-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    rs6000:LynxOS:2.*:*)
+       echo rs6000-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+       echo powerpc-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    SM[BE]S:UNIX_SV:*:*)
+       echo mips-dde-sysv${UNAME_RELEASE}
+       exit 0 ;;
+    RM*:ReliantUNIX-*:*:*)
+       echo mips-sni-sysv4
+       exit 0 ;;
+    RM*:SINIX-*:*:*)
+       echo mips-sni-sysv4
+       exit 0 ;;
+    *:SINIX-*:*:*)
+       if uname -p 2>/dev/null >/dev/null ; then
+               UNAME_MACHINE=`(uname -p) 2>/dev/null`
+               echo ${UNAME_MACHINE}-sni-sysv4
+       else
+               echo ns32k-sni-sysv
+       fi
+       exit 0 ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit 0 ;;
+    *:UNIX_System_V:4*:FTX*)
+       # From Gerald Hewes <hewes@openmarket.com>.
+       # How about differentiating between stratus architectures? -djm
+       echo hppa1.1-stratus-sysv4
+       exit 0 ;;
+    *:*:*:FTX*)
+       # From seanf@swdc.stratus.com.
+       echo i860-stratus-sysv4
+       exit 0 ;;
+    *:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo hppa1.1-stratus-vos
+       exit 0 ;;
+    mc68*:A/UX:*:*)
+       echo m68k-apple-aux${UNAME_RELEASE}
+       exit 0 ;;
+    news*:NEWS-OS:6*:*)
+       echo mips-sony-newsos6
+       exit 0 ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+       if [ -d /usr/nec ]; then
+               echo mips-nec-sysv${UNAME_RELEASE}
+       else
+               echo mips-unknown-sysv${UNAME_RELEASE}
+       fi
+        exit 0 ;;
+    BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
+       echo powerpc-be-beos
+       exit 0 ;;
+    BeMac:BeOS:*:*)    # BeOS running on Mac or Mac clone, PPC only.
+       echo powerpc-apple-beos
+       exit 0 ;;
+    BePC:BeOS:*:*)     # BeOS running on Intel PC compatible.
+       echo i586-pc-beos
+       exit 0 ;;
+    SX-4:SUPER-UX:*:*)
+       echo sx4-nec-superux${UNAME_RELEASE}
+       exit 0 ;;
+    SX-5:SUPER-UX:*:*)
+       echo sx5-nec-superux${UNAME_RELEASE}
+       exit 0 ;;
+    Power*:Rhapsody:*:*)
+       echo powerpc-apple-rhapsody${UNAME_RELEASE}
+       exit 0 ;;
+    *:Rhapsody:*:*)
+       echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+       exit 0 ;;
+    *:Darwin:*:*)
+       echo `uname -p`-apple-darwin${UNAME_RELEASE}
+       exit 0 ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+       UNAME_PROCESSOR=`uname -p`
+       if test "$UNAME_PROCESSOR" = "x86"; then
+               UNAME_PROCESSOR=i386
+               UNAME_MACHINE=pc
+       fi
+       echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+       exit 0 ;;
+    *:QNX:*:4*)
+       echo i386-pc-qnx
+       exit 0 ;;
+    NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*)
+       echo nsr-tandem-nsk${UNAME_RELEASE}
+       exit 0 ;;
+    *:NonStop-UX:*:*)
+       echo mips-compaq-nonstopux
+       exit 0 ;;
+    BS2000:POSIX*:*:*)
+       echo bs2000-siemens-sysv
+       exit 0 ;;
+    DS/*:UNIX_System_V:*:*)
+       echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+       exit 0 ;;
+    *:Plan9:*:*)
+       # "uname -m" is not consistent, so use $cputype instead. 386
+       # is converted to i386 for consistency with other x86
+       # operating systems.
+       if test "$cputype" = "386"; then
+           UNAME_MACHINE=i386
+       else
+           UNAME_MACHINE="$cputype"
+       fi
+       echo ${UNAME_MACHINE}-unknown-plan9
+       exit 0 ;;
+    i*86:OS/2:*:*)
+       # If we were able to find `uname', then EMX Unix compatibility
+       # is probably installed.
+       echo ${UNAME_MACHINE}-pc-os2-emx
+       exit 0 ;;
+    *:TOPS-10:*:*)
+       echo pdp10-unknown-tops10
+       exit 0 ;;
+    *:TENEX:*:*)
+       echo pdp10-unknown-tenex
+       exit 0 ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+       echo pdp10-dec-tops20
+       exit 0 ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+       echo pdp10-xkl-tops20
+       exit 0 ;;
+    *:TOPS-20:*:*)
+       echo pdp10-unknown-tops20
+       exit 0 ;;
+    *:ITS:*:*)
+       echo pdp10-unknown-its
+       exit 0 ;;
+    i*86:XTS-300:*:STOP)
+       echo ${UNAME_MACHINE}-unknown-stop
+       exit 0 ;;
+    i*86:atheos:*:*)
+       echo ${UNAME_MACHINE}-unknown-atheos
+       exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+         ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+       printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+       printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0
+rm -f $dummy.c $dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+       echo c1-convex-bsd
+       exit 0 ;;
+    c2*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+       exit 0 ;;
+    c34*)
+       echo c34-convex-bsd
+       exit 0 ;;
+    c38*)
+       echo c38-convex-bsd
+       exit 0 ;;
+    c4*)
+       echo c4-convex-bsd
+       exit 0 ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+    ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.h.in b/config.h.in
new file mode 100644 (file)
index 0000000..44ab1f7
--- /dev/null
@@ -0,0 +1,78 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define it if GAS requires that absolute indirect calls/jumps are not
+   prefixed with an asterisk */
+#undef ABSOLUTE_WITHOUT_ASTERISK
+
+/* Define it to "addr32" or "addr32;" to make GAS happy */
+#undef ADDR32
+
+/* Define it to one of __bss_start, edata and _edata */
+#undef BSS_START_SYMBOL
+
+/* Define it to "data32" or "data32;" to make GAS happy */
+#undef DATA32
+
+/* Define it to either end or _end */
+#undef END_SYMBOL
+
+/* Define if C symbols get an underscore after compilation */
+#undef HAVE_ASM_USCORE
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* The size of a `long', as computed by sizeof. */
+#undef SIZEOF_LONG
+
+/* The size of a `void *', as computed by sizeof. */
+#undef SIZEOF_VOID_P
+
+/* Define it to either start or _start */
+#undef START_SYMBOL
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
diff --git a/config.sub b/config.sub
new file mode 100644 (file)
index 0000000..299f3f4
--- /dev/null
@@ -0,0 +1,1443 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002 Free Software Foundation, Inc.
+
+timestamp='2002-04-26'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#      CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#      CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit 0;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+       -sun*os*)
+               # Prevent following clause from handling this invalid input.
+               ;;
+       -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+       -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+       -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+       -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+       -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+       -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+       -apple | -axis)
+               os=
+               basic_machine=$1
+               ;;
+       -sim | -cisco | -oki | -wec | -winbond)
+               os=
+               basic_machine=$1
+               ;;
+       -scout)
+               ;;
+       -wrs)
+               os=-vxworks
+               basic_machine=$1
+               ;;
+       -chorusos*)
+               os=-chorusos
+               basic_machine=$1
+               ;;
+       -chorusrdb)
+               os=-chorusrdb
+               basic_machine=$1
+               ;;
+       -hiux*)
+               os=-hiuxwe2
+               ;;
+       -sco5)
+               os=-sco3.2v5
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco4)
+               os=-sco3.2v4
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2.[4-9]*)
+               os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2v[4-9]*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco*)
+               os=-sco3.2v2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -udk*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -isc)
+               os=-isc2.2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -clix*)
+               basic_machine=clipper-intergraph
+               ;;
+       -isc*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -lynx*)
+               os=-lynxos
+               ;;
+       -ptx*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+               ;;
+       -windowsnt*)
+               os=`echo $os | sed -e 's/windowsnt/winnt/'`
+               ;;
+       -psos*)
+               os=-psos
+               ;;
+       -mint | -mint[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+       # Recognize the basic CPU types without company name.
+       # Some are omitted here because they have special meanings below.
+       1750a | 580 \
+       | a29k \
+       | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+       | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+       | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+       | c4x | clipper \
+       | d10v | d30v | dsp16xx \
+       | fr30 \
+       | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+       | i370 | i860 | i960 | ia64 \
+       | m32r | m68000 | m68k | m88k | mcore \
+       | mips | mips16 | mips64 | mips64el | mips64orion | mips64orionel \
+       | mips64vr4100 | mips64vr4100el | mips64vr4300 \
+       | mips64vr4300el | mips64vr5000 | mips64vr5000el \
+       | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \
+       | mipsisa32 | mipsisa64 \
+       | mn10200 | mn10300 \
+       | ns16k | ns32k \
+       | openrisc | or32 \
+       | pdp10 | pdp11 | pj | pjl \
+       | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+       | pyramid \
+       | sh | sh[34] | sh[34]eb | shbe | shle | sh64 \
+       | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
+       | strongarm \
+       | tahoe | thumb | tic80 | tron \
+       | v850 | v850e \
+       | we32k \
+       | x86 | xscale | xstormy16 | xtensa \
+       | z8k)
+               basic_machine=$basic_machine-unknown
+               ;;
+       m6811 | m68hc11 | m6812 | m68hc12)
+               # Motorola 68HC11/12.
+               basic_machine=$basic_machine-unknown
+               os=-none
+               ;;
+       m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+               ;;
+
+       # We use `pc' rather than `unknown'
+       # because (1) that's what they normally are, and
+       # (2) the word "unknown" tends to confuse beginning users.
+       i*86 | x86_64)
+         basic_machine=$basic_machine-pc
+         ;;
+       # Object if more than one company name word.
+       *-*-*)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+       # Recognize the basic CPU types with company name.
+       580-* \
+       | a29k-* \
+       | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+       | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+       | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+       | arm-*  | armbe-* | armle-* | armv*-* \
+       | avr-* \
+       | bs2000-* \
+       | c[123]* | c30-* | [cjt]90-* | c54x-* \
+       | clipper-* | cydra-* \
+       | d10v-* | d30v-* \
+       | elxsi-* \
+       | f30[01]-* | f700-* | fr30-* | fx80-* \
+       | h8300-* | h8500-* \
+       | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+       | i*86-* | i860-* | i960-* | ia64-* \
+       | m32r-* \
+       | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+       | m88110-* | m88k-* | mcore-* \
+       | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \
+       | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \
+       | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \
+       | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \
+       | none-* | np1-* | ns16k-* | ns32k-* \
+       | orion-* \
+       | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+       | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+       | pyramid-* \
+       | romp-* | rs6000-* \
+       | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* | sh64-* \
+       | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+       | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+       | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \
+       | v850-* | v850e-* | vax-* \
+       | we32k-* \
+       | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+       | xtensa-* \
+       | ymp-* \
+       | z8k-*)
+               ;;
+       # Recognize the various machine names and aliases which stand
+       # for a CPU type and a company and sometimes even an OS.
+       386bsd)
+               basic_machine=i386-unknown
+               os=-bsd
+               ;;
+       3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+               basic_machine=m68000-att
+               ;;
+       3b*)
+               basic_machine=we32k-att
+               ;;
+       a29khif)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       adobe68k)
+               basic_machine=m68010-adobe
+               os=-scout
+               ;;
+       alliant | fx80)
+               basic_machine=fx80-alliant
+               ;;
+       altos | altos3068)
+               basic_machine=m68k-altos
+               ;;
+       am29k)
+               basic_machine=a29k-none
+               os=-bsd
+               ;;
+       amdahl)
+               basic_machine=580-amdahl
+               os=-sysv
+               ;;
+       amiga | amiga-*)
+               basic_machine=m68k-unknown
+               ;;
+       amigaos | amigados)
+               basic_machine=m68k-unknown
+               os=-amigaos
+               ;;
+       amigaunix | amix)
+               basic_machine=m68k-unknown
+               os=-sysv4
+               ;;
+       apollo68)
+               basic_machine=m68k-apollo
+               os=-sysv
+               ;;
+       apollo68bsd)
+               basic_machine=m68k-apollo
+               os=-bsd
+               ;;
+       aux)
+               basic_machine=m68k-apple
+               os=-aux
+               ;;
+       balance)
+               basic_machine=ns32k-sequent
+               os=-dynix
+               ;;
+       c90)
+               basic_machine=c90-cray
+               os=-unicos
+               ;;
+       convex-c1)
+               basic_machine=c1-convex
+               os=-bsd
+               ;;
+       convex-c2)
+               basic_machine=c2-convex
+               os=-bsd
+               ;;
+       convex-c32)
+               basic_machine=c32-convex
+               os=-bsd
+               ;;
+       convex-c34)
+               basic_machine=c34-convex
+               os=-bsd
+               ;;
+       convex-c38)
+               basic_machine=c38-convex
+               os=-bsd
+               ;;
+       cray | j90)
+               basic_machine=j90-cray
+               os=-unicos
+               ;;
+       crds | unos)
+               basic_machine=m68k-crds
+               ;;
+       cris | cris-* | etrax*)
+               basic_machine=cris-axis
+               ;;
+       da30 | da30-*)
+               basic_machine=m68k-da30
+               ;;
+       decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+               basic_machine=mips-dec
+               ;;
+       decsystem10* | dec10*)
+               basic_machine=pdp10-dec
+               os=-tops10
+               ;;
+       decsystem20* | dec20*)
+               basic_machine=pdp10-dec
+               os=-tops20
+               ;;
+       delta | 3300 | motorola-3300 | motorola-delta \
+             | 3300-motorola | delta-motorola)
+               basic_machine=m68k-motorola
+               ;;
+       delta88)
+               basic_machine=m88k-motorola
+               os=-sysv3
+               ;;
+       dpx20 | dpx20-*)
+               basic_machine=rs6000-bull
+               os=-bosx
+               ;;
+       dpx2* | dpx2*-bull)
+               basic_machine=m68k-bull
+               os=-sysv3
+               ;;
+       ebmon29k)
+               basic_machine=a29k-amd
+               os=-ebmon
+               ;;
+       elxsi)
+               basic_machine=elxsi-elxsi
+               os=-bsd
+               ;;
+       encore | umax | mmax)
+               basic_machine=ns32k-encore
+               ;;
+       es1800 | OSE68k | ose68k | ose | OSE)
+               basic_machine=m68k-ericsson
+               os=-ose
+               ;;
+       fx2800)
+               basic_machine=i860-alliant
+               ;;
+       genix)
+               basic_machine=ns32k-ns
+               ;;
+       gmicro)
+               basic_machine=tron-gmicro
+               os=-sysv
+               ;;
+       go32)
+               basic_machine=i386-pc
+               os=-go32
+               ;;
+       h3050r* | hiux*)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       h8300hms)
+               basic_machine=h8300-hitachi
+               os=-hms
+               ;;
+       h8300xray)
+               basic_machine=h8300-hitachi
+               os=-xray
+               ;;
+       h8500hms)
+               basic_machine=h8500-hitachi
+               os=-hms
+               ;;
+       harris)
+               basic_machine=m88k-harris
+               os=-sysv3
+               ;;
+       hp300-*)
+               basic_machine=m68k-hp
+               ;;
+       hp300bsd)
+               basic_machine=m68k-hp
+               os=-bsd
+               ;;
+       hp300hpux)
+               basic_machine=m68k-hp
+               os=-hpux
+               ;;
+       hp3k9[0-9][0-9] | hp9[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k2[0-9][0-9] | hp9k31[0-9])
+               basic_machine=m68000-hp
+               ;;
+       hp9k3[2-9][0-9])
+               basic_machine=m68k-hp
+               ;;
+       hp9k6[0-9][0-9] | hp6[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k7[0-79][0-9] | hp7[0-79][0-9])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k78[0-9] | hp78[0-9])
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][13679] | hp8[0-9][13679])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][0-9] | hp8[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hppa-next)
+               os=-nextstep3
+               ;;
+       hppaosf)
+               basic_machine=hppa1.1-hp
+               os=-osf
+               ;;
+       hppro)
+               basic_machine=hppa1.1-hp
+               os=-proelf
+               ;;
+       i370-ibm* | ibm*)
+               basic_machine=i370-ibm
+               ;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+       i*86v32)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv32
+               ;;
+       i*86v4*)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv4
+               ;;
+       i*86v)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv
+               ;;
+       i*86sol2)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-solaris2
+               ;;
+       i386mach)
+               basic_machine=i386-mach
+               os=-mach
+               ;;
+       i386-vsta | vsta)
+               basic_machine=i386-unknown
+               os=-vsta
+               ;;
+       iris | iris4d)
+               basic_machine=mips-sgi
+               case $os in
+                   -irix*)
+                       ;;
+                   *)
+                       os=-irix4
+                       ;;
+               esac
+               ;;
+       isi68 | isi)
+               basic_machine=m68k-isi
+               os=-sysv
+               ;;
+       m88k-omron*)
+               basic_machine=m88k-omron
+               ;;
+       magnum | m3230)
+               basic_machine=mips-mips
+               os=-sysv
+               ;;
+       merlin)
+               basic_machine=ns32k-utek
+               os=-sysv
+               ;;
+       mingw32)
+               basic_machine=i386-pc
+               os=-mingw32
+               ;;
+       miniframe)
+               basic_machine=m68000-convergent
+               ;;
+       *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+       mips3*-*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+               ;;
+       mips3*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+               ;;
+       mmix*)
+               basic_machine=mmix-knuth
+               os=-mmixware
+               ;;
+       monitor)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       morphos)
+               basic_machine=powerpc-unknown
+               os=-morphos
+               ;;
+       msdos)
+               basic_machine=i386-pc
+               os=-msdos
+               ;;
+       mvs)
+               basic_machine=i370-ibm
+               os=-mvs
+               ;;
+       ncr3000)
+               basic_machine=i486-ncr
+               os=-sysv4
+               ;;
+       netbsd386)
+               basic_machine=i386-unknown
+               os=-netbsd
+               ;;
+       netwinder)
+               basic_machine=armv4l-rebel
+               os=-linux
+               ;;
+       news | news700 | news800 | news900)
+               basic_machine=m68k-sony
+               os=-newsos
+               ;;
+       news1000)
+               basic_machine=m68030-sony
+               os=-newsos
+               ;;
+       news-3600 | risc-news)
+               basic_machine=mips-sony
+               os=-newsos
+               ;;
+       necv70)
+               basic_machine=v70-nec
+               os=-sysv
+               ;;
+       next | m*-next )
+               basic_machine=m68k-next
+               case $os in
+                   -nextstep* )
+                       ;;
+                   -ns2*)
+                     os=-nextstep2
+                       ;;
+                   *)
+                     os=-nextstep3
+                       ;;
+               esac
+               ;;
+       nh3000)
+               basic_machine=m68k-harris
+               os=-cxux
+               ;;
+       nh[45]000)
+               basic_machine=m88k-harris
+               os=-cxux
+               ;;
+       nindy960)
+               basic_machine=i960-intel
+               os=-nindy
+               ;;
+       mon960)
+               basic_machine=i960-intel
+               os=-mon960
+               ;;
+       nonstopux)
+               basic_machine=mips-compaq
+               os=-nonstopux
+               ;;
+       np1)
+               basic_machine=np1-gould
+               ;;
+       nsr-tandem)
+               basic_machine=nsr-tandem
+               ;;
+       op50n-* | op60c-*)
+               basic_machine=hppa1.1-oki
+               os=-proelf
+               ;;
+       or32 | or32-*)
+               basic_machine=or32-unknown
+               os=-coff
+               ;;
+       OSE68000 | ose68000)
+               basic_machine=m68000-ericsson
+               os=-ose
+               ;;
+       os68k)
+               basic_machine=m68k-none
+               os=-os68k
+               ;;
+       pa-hitachi)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       paragon)
+               basic_machine=i860-intel
+               os=-osf
+               ;;
+       pbd)
+               basic_machine=sparc-tti
+               ;;
+       pbb)
+               basic_machine=m68k-tti
+               ;;
+        pc532 | pc532-*)
+               basic_machine=ns32k-pc532
+               ;;
+       pentium | p5 | k5 | k6 | nexgen | viac3)
+               basic_machine=i586-pc
+               ;;
+       pentiumpro | p6 | 6x86 | athlon)
+               basic_machine=i686-pc
+               ;;
+       pentiumii | pentium2)
+               basic_machine=i686-pc
+               ;;
+       pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+               basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumpro-* | p6-* | 6x86-* | athlon-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumii-* | pentium2-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pn)
+               basic_machine=pn-gould
+               ;;
+       power)  basic_machine=power-ibm
+               ;;
+       ppc)    basic_machine=powerpc-unknown
+               ;;
+       ppc-*)  basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppcle | powerpclittle | ppc-le | powerpc-little)
+               basic_machine=powerpcle-unknown
+               ;;
+       ppcle-* | powerpclittle-*)
+               basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64)  basic_machine=powerpc64-unknown
+               ;;
+       ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+               basic_machine=powerpc64le-unknown
+               ;;
+       ppc64le-* | powerpc64little-*)
+               basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ps2)
+               basic_machine=i386-ibm
+               ;;
+       pw32)
+               basic_machine=i586-unknown
+               os=-pw32
+               ;;
+       rom68k)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       rm[46]00)
+               basic_machine=mips-siemens
+               ;;
+       rtpc | rtpc-*)
+               basic_machine=romp-ibm
+               ;;
+       s390 | s390-*)
+               basic_machine=s390-ibm
+               ;;
+       s390x | s390x-*)
+               basic_machine=s390x-ibm
+               ;;
+       sa29200)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       sequent)
+               basic_machine=i386-sequent
+               ;;
+       sh)
+               basic_machine=sh-hitachi
+               os=-hms
+               ;;
+       sparclite-wrs | simso-wrs)
+               basic_machine=sparclite-wrs
+               os=-vxworks
+               ;;
+       sps7)
+               basic_machine=m68k-bull
+               os=-sysv2
+               ;;
+       spur)
+               basic_machine=spur-unknown
+               ;;
+       st2000)
+               basic_machine=m68k-tandem
+               ;;
+       stratus)
+               basic_machine=i860-stratus
+               os=-sysv4
+               ;;
+       sun2)
+               basic_machine=m68000-sun
+               ;;
+       sun2os3)
+               basic_machine=m68000-sun
+               os=-sunos3
+               ;;
+       sun2os4)
+               basic_machine=m68000-sun
+               os=-sunos4
+               ;;
+       sun3os3)
+               basic_machine=m68k-sun
+               os=-sunos3
+               ;;
+       sun3os4)
+               basic_machine=m68k-sun
+               os=-sunos4
+               ;;
+       sun4os3)
+               basic_machine=sparc-sun
+               os=-sunos3
+               ;;
+       sun4os4)
+               basic_machine=sparc-sun
+               os=-sunos4
+               ;;
+       sun4sol2)
+               basic_machine=sparc-sun
+               os=-solaris2
+               ;;
+       sun3 | sun3-*)
+               basic_machine=m68k-sun
+               ;;
+       sun4)
+               basic_machine=sparc-sun
+               ;;
+       sun386 | sun386i | roadrunner)
+               basic_machine=i386-sun
+               ;;
+        sv1)
+               basic_machine=sv1-cray
+               os=-unicos
+               ;;
+       symmetry)
+               basic_machine=i386-sequent
+               os=-dynix
+               ;;
+       t3d)
+               basic_machine=alpha-cray
+               os=-unicos
+               ;;
+       t3e)
+               basic_machine=alphaev5-cray
+               os=-unicos
+               ;;
+       t90)
+               basic_machine=t90-cray
+               os=-unicos
+               ;;
+       tic54x | c54x*)
+               basic_machine=tic54x-unknown
+               os=-coff
+               ;;
+       tx39)
+               basic_machine=mipstx39-unknown
+               ;;
+       tx39el)
+               basic_machine=mipstx39el-unknown
+               ;;
+       toad1)
+               basic_machine=pdp10-xkl
+               os=-tops20
+               ;;
+       tower | tower-32)
+               basic_machine=m68k-ncr
+               ;;
+       udi29k)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       ultra3)
+               basic_machine=a29k-nyu
+               os=-sym1
+               ;;
+       v810 | necv810)
+               basic_machine=v810-nec
+               os=-none
+               ;;
+       vaxv)
+               basic_machine=vax-dec
+               os=-sysv
+               ;;
+       vms)
+               basic_machine=vax-dec
+               os=-vms
+               ;;
+       vpp*|vx|vx-*)
+               basic_machine=f301-fujitsu
+               ;;
+       vxworks960)
+               basic_machine=i960-wrs
+               os=-vxworks
+               ;;
+       vxworks68)
+               basic_machine=m68k-wrs
+               os=-vxworks
+               ;;
+       vxworks29k)
+               basic_machine=a29k-wrs
+               os=-vxworks
+               ;;
+       w65*)
+               basic_machine=w65-wdc
+               os=-none
+               ;;
+       w89k-*)
+               basic_machine=hppa1.1-winbond
+               os=-proelf
+               ;;
+       windows32)
+               basic_machine=i386-pc
+               os=-windows32-msvcrt
+               ;;
+        xps | xps100)
+               basic_machine=xps100-honeywell
+               ;;
+       ymp)
+               basic_machine=ymp-cray
+               os=-unicos
+               ;;
+       z8k-*-coff)
+               basic_machine=z8k-unknown
+               os=-sim
+               ;;
+       none)
+               basic_machine=none-none
+               os=-none
+               ;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+       w89k)
+               basic_machine=hppa1.1-winbond
+               ;;
+       op50n)
+               basic_machine=hppa1.1-oki
+               ;;
+       op60c)
+               basic_machine=hppa1.1-oki
+               ;;
+       romp)
+               basic_machine=romp-ibm
+               ;;
+       rs6000)
+               basic_machine=rs6000-ibm
+               ;;
+       vax)
+               basic_machine=vax-dec
+               ;;
+       pdp10)
+               # there are many clones, so DEC is not a safe bet
+               basic_machine=pdp10-unknown
+               ;;
+       pdp11)
+               basic_machine=pdp11-dec
+               ;;
+       we32k)
+               basic_machine=we32k-att
+               ;;
+       sh3 | sh4 | sh3eb | sh4eb)
+               basic_machine=sh-unknown
+               ;;
+       sh64)
+               basic_machine=sh64-unknown
+               ;;
+       sparc | sparcv9 | sparcv9b)
+               basic_machine=sparc-sun
+               ;;
+        cydra)
+               basic_machine=cydra-cydrome
+               ;;
+       orion)
+               basic_machine=orion-highlevel
+               ;;
+       orion105)
+               basic_machine=clipper-highlevel
+               ;;
+       mac | mpw | mac-mpw)
+               basic_machine=m68k-apple
+               ;;
+       pmac | pmac-mpw)
+               basic_machine=powerpc-apple
+               ;;
+       c4x*)
+               basic_machine=c4x-none
+               os=-coff
+               ;;
+       *-unknown)
+               # Make sure to match an already-canonicalized machine name.
+               ;;
+       *)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+       *-digital*)
+               basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+               ;;
+       *-commodore*)
+               basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+               ;;
+       *)
+               ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+       # -solaris* is a basic system type, with this one exception.
+       -solaris1 | -solaris1.*)
+               os=`echo $os | sed -e 's|solaris1|sunos4|'`
+               ;;
+       -solaris)
+               os=-solaris2
+               ;;
+       -svr4*)
+               os=-sysv4
+               ;;
+       -unixware*)
+               os=-sysv4.2uw
+               ;;
+       -gnu/linux*)
+               os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+               ;;
+       # First accept the basic system types.
+       # The portable systems comes first.
+       # Each alternative MUST END IN A *, to match a version number.
+       # -sysv* is not here because it comes later, after sysvr4.
+       -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+             | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+             | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+             | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+             | -aos* \
+             | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+             | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+             | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+             | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+             | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+             | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+             | -chorusos* | -chorusrdb* \
+             | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+             | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+             | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
+             | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+             | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+             | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+             | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* )
+       # Remember, each alternative MUST END IN *, to match a version number.
+               ;;
+       -qnx*)
+               case $basic_machine in
+                   x86-* | i*86-*)
+                       ;;
+                   *)
+                       os=-nto$os
+                       ;;
+               esac
+               ;;
+       -nto*)
+               os=-nto-qnx
+               ;;
+       -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+             | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+             | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+               ;;
+       -mac*)
+               os=`echo $os | sed -e 's|mac|macos|'`
+               ;;
+       -linux*)
+               os=`echo $os | sed -e 's|linux|linux-gnu|'`
+               ;;
+       -sunos5*)
+               os=`echo $os | sed -e 's|sunos5|solaris2|'`
+               ;;
+       -sunos6*)
+               os=`echo $os | sed -e 's|sunos6|solaris3|'`
+               ;;
+       -opened*)
+               os=-openedition
+               ;;
+       -wince*)
+               os=-wince
+               ;;
+       -osfrose*)
+               os=-osfrose
+               ;;
+       -osf*)
+               os=-osf
+               ;;
+       -utek*)
+               os=-bsd
+               ;;
+       -dynix*)
+               os=-bsd
+               ;;
+       -acis*)
+               os=-aos
+               ;;
+       -atheos*)
+               os=-atheos
+               ;;
+       -386bsd)
+               os=-bsd
+               ;;
+       -ctix* | -uts*)
+               os=-sysv
+               ;;
+       -nova*)
+               os=-rtmk-nova
+               ;;
+       -ns2 )
+               os=-nextstep2
+               ;;
+       -nsk*)
+               os=-nsk
+               ;;
+       # Preserve the version number of sinix5.
+       -sinix5.*)
+               os=`echo $os | sed -e 's|sinix|sysv|'`
+               ;;
+       -sinix*)
+               os=-sysv4
+               ;;
+       -triton*)
+               os=-sysv3
+               ;;
+       -oss*)
+               os=-sysv3
+               ;;
+       -svr4)
+               os=-sysv4
+               ;;
+       -svr3)
+               os=-sysv3
+               ;;
+       -sysvr4)
+               os=-sysv4
+               ;;
+       # This must come after -sysvr4.
+       -sysv*)
+               ;;
+       -ose*)
+               os=-ose
+               ;;
+       -es1800*)
+               os=-ose
+               ;;
+       -xenix)
+               os=-xenix
+               ;;
+        -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+               os=-mint
+               ;;
+       -none)
+               ;;
+       *)
+               # Get rid of the `-' at the beginning of $os.
+               os=`echo $os | sed 's/[^-]*-//'`
+               echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+       *-acorn)
+               os=-riscix1.2
+               ;;
+       arm*-rebel)
+               os=-linux
+               ;;
+       arm*-semi)
+               os=-aout
+               ;;
+       # This must come before the *-dec entry.
+       pdp10-*)
+               os=-tops20
+               ;;
+        pdp11-*)
+               os=-none
+               ;;
+       *-dec | vax-*)
+               os=-ultrix4.2
+               ;;
+       m68*-apollo)
+               os=-domain
+               ;;
+       i386-sun)
+               os=-sunos4.0.2
+               ;;
+       m68000-sun)
+               os=-sunos3
+               # This also exists in the configure program, but was not the
+               # default.
+               # os=-sunos4
+               ;;
+       m68*-cisco)
+               os=-aout
+               ;;
+       mips*-cisco)
+               os=-elf
+               ;;
+       mips*-*)
+               os=-elf
+               ;;
+       or32-*)
+               os=-coff
+               ;;
+       *-tti)  # must be before sparc entry or we get the wrong os.
+               os=-sysv3
+               ;;
+       sparc-* | *-sun)
+               os=-sunos4.1.1
+               ;;
+       *-be)
+               os=-beos
+               ;;
+       *-ibm)
+               os=-aix
+               ;;
+       *-wec)
+               os=-proelf
+               ;;
+       *-winbond)
+               os=-proelf
+               ;;
+       *-oki)
+               os=-proelf
+               ;;
+       *-hp)
+               os=-hpux
+               ;;
+       *-hitachi)
+               os=-hiux
+               ;;
+       i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+               os=-sysv
+               ;;
+       *-cbm)
+               os=-amigaos
+               ;;
+       *-dg)
+               os=-dgux
+               ;;
+       *-dolphin)
+               os=-sysv3
+               ;;
+       m68k-ccur)
+               os=-rtu
+               ;;
+       m88k-omron*)
+               os=-luna
+               ;;
+       *-next )
+               os=-nextstep
+               ;;
+       *-sequent)
+               os=-ptx
+               ;;
+       *-crds)
+               os=-unos
+               ;;
+       *-ns)
+               os=-genix
+               ;;
+       i370-*)
+               os=-mvs
+               ;;
+       *-next)
+               os=-nextstep3
+               ;;
+        *-gould)
+               os=-sysv
+               ;;
+        *-highlevel)
+               os=-bsd
+               ;;
+       *-encore)
+               os=-bsd
+               ;;
+        *-sgi)
+               os=-irix
+               ;;
+        *-siemens)
+               os=-sysv4
+               ;;
+       *-masscomp)
+               os=-rtu
+               ;;
+       f30[01]-fujitsu | f700-fujitsu)
+               os=-uxpv
+               ;;
+       *-rom68k)
+               os=-coff
+               ;;
+       *-*bug)
+               os=-coff
+               ;;
+       *-apple)
+               os=-macos
+               ;;
+       *-atari*)
+               os=-mint
+               ;;
+       *)
+               os=-none
+               ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+       *-unknown)
+               case $os in
+                       -riscix*)
+                               vendor=acorn
+                               ;;
+                       -sunos*)
+                               vendor=sun
+                               ;;
+                       -aix*)
+                               vendor=ibm
+                               ;;
+                       -beos*)
+                               vendor=be
+                               ;;
+                       -hpux*)
+                               vendor=hp
+                               ;;
+                       -mpeix*)
+                               vendor=hp
+                               ;;
+                       -hiux*)
+                               vendor=hitachi
+                               ;;
+                       -unos*)
+                               vendor=crds
+                               ;;
+                       -dgux*)
+                               vendor=dg
+                               ;;
+                       -luna*)
+                               vendor=omron
+                               ;;
+                       -genix*)
+                               vendor=ns
+                               ;;
+                       -mvs* | -opened*)
+                               vendor=ibm
+                               ;;
+                       -ptx*)
+                               vendor=sequent
+                               ;;
+                       -vxsim* | -vxworks* | -windiss*)
+                               vendor=wrs
+                               ;;
+                       -aux*)
+                               vendor=apple
+                               ;;
+                       -hms*)
+                               vendor=hitachi
+                               ;;
+                       -mpw* | -macos*)
+                               vendor=apple
+                               ;;
+                       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+                               vendor=atari
+                               ;;
+                       -vos*)
+                               vendor=stratus
+                               ;;
+               esac
+               basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+               ;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/configure b/configure
new file mode 100644 (file)
index 0000000..45a328b
--- /dev/null
+++ b/configure
@@ -0,0 +1,5745 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.53 for PUPA 0.6.
+#
+# Report bugs to <okuji@enbug.org>.
+#
+# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+# Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+
+# NLS nuisances.
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+(set +x; test -n "`(LANG=C; export LANG) 2>&1`") &&
+    { $as_unset LANG || test "${LANG+set}" != set; } ||
+      { LANG=C; export LANG; }
+(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") &&
+    { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } ||
+      { LC_ALL=C; export LC_ALL; }
+(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") &&
+    { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } ||
+      { LC_TIME=C; export LC_TIME; }
+(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") &&
+    { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } ||
+      { LC_CTYPE=C; export LC_CTYPE; }
+(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") &&
+    { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } ||
+      { LANGUAGE=C; export LANGUAGE; }
+(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") &&
+    { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } ||
+      { LC_COLLATE=C; export LC_COLLATE; }
+(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") &&
+    { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } ||
+      { LC_NUMERIC=C; export LC_NUMERIC; }
+(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") &&
+    { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } ||
+      { LC_MESSAGES=C; export LC_MESSAGES; }
+
+
+# Name of the executable.
+as_me=`(basename "$0") 2>/dev/null ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)$' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+         /^X\/\(\/\/\)$/{ s//\1/; q; }
+         /^X\/\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conftest.sh
+  echo  "exit 0"   >>conftest.sh
+  chmod +x conftest.sh
+  if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conftest.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+        case $as_dir in
+        /*)
+          if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+            CONFIG_SHELL=$as_dir/$as_base
+            export CONFIG_SHELL
+            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+          fi;;
+        esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='     ' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS="  $as_nl"
+
+# CDPATH.
+$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; }
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete.  It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME='PUPA'
+PACKAGE_TARNAME='pupa'
+PACKAGE_VERSION='0.6'
+PACKAGE_STRING='PUPA 0.6'
+PACKAGE_BUGREPORT='okuji@enbug.org'
+
+ac_unique_file="include/pupa/dl.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_option in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    eval "enable_$ac_feature=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+   { (exit 1); exit 1; }; }
+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_$ac_feature='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_$ac_package='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid package name: $ac_package" >&2
+   { (exit 1); exit 1; }; }
+    ac_package=`echo $ac_package | sed 's/-/_/g'`
+    eval "with_$ac_package=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+    eval "$ac_envvar='$ac_optarg'"
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+              localstatedir libdir includedir oldincludedir infodir mandir
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$0" : 'X\(//\)[^/]' \| \
+         X"$0" : 'X\(//\)$' \| \
+         X"$0" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+   { (exit 1); exit 1; }; }
+  else
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+  fi
+fi
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures PUPA 0.6 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+  cat <<_ACEOF
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [EPREFIX/bin]
+  --sbindir=DIR          system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
+  --libdir=DIR           object code libraries [EPREFIX/lib]
+  --includedir=DIR       C header files [PREFIX/include]
+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
+  --infodir=DIR          info documentation [PREFIX/info]
+  --mandir=DIR           man documentation [PREFIX/man]
+_ACEOF
+
+  cat <<\_ACEOF
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of PUPA 0.6:";;
+   esac
+  cat <<\_ACEOF
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <okuji@enbug.org>.
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  ac_popdir=`pwd`
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d $ac_dir || continue
+    ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+# absolute.
+ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd`
+ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+
+    cd $ac_dir
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      echo
+      $SHELL $ac_srcdir/configure.gnu  --help=recursive
+    elif test -f $ac_srcdir/configure; then
+      echo
+      $SHELL $ac_srcdir/configure  --help=recursive
+    elif test -f $ac_srcdir/configure.ac ||
+           test -f $ac_srcdir/configure.in; then
+      echo
+      $ac_configure --help
+    else
+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi
+    cd $ac_popdir
+  done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+  cat <<\_ACEOF
+PUPA configure 0.6
+generated by GNU Autoconf 2.53
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by PUPA $as_me 0.6, which was
+generated by GNU Autoconf 2.53.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell meta-characters.
+ac_configure_args=
+ac_sep=
+for ac_arg
+do
+  case $ac_arg in
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n ) continue ;;
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    continue ;;
+  *" "*|*"     "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+    ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+  esac
+  case " $ac_configure_args " in
+    *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+    *) ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+       ac_sep=" " ;;
+  esac
+  # Get rid of the leading space.
+done
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+{
+  (set) 2>&1 |
+    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      sed -n \
+        "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+      ;;
+    *)
+      sed -n \
+        "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+}
+    echo
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      sed "/^$/d" confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      echo "$as_me: caught signal $ac_signal"
+    echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core core.* *.core &&
+  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+     ' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
+    esac
+  fi
+else
+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+               sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+  eval ac_new_val="\$ac_env_${ac_var}_value"
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+        { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+        { echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
+echo "$as_me:   former value:  $ac_old_val" >&2;}
+        { echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
+echo "$as_me:   current value: $ac_new_val" >&2;}
+        ac_cache_corrupted=:
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+# Checks for build and host systems.
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f $ac_dir/shtool; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+# Make sure we can run config.sub.
+$ac_config_sub sun4 >/dev/null 2>&1 ||
+  { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5
+echo "$as_me: error: cannot run $ac_config_sub" >&2;}
+   { (exit 1); exit 1; }; }
+
+echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6
+if test "${ac_cv_build+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_build_alias=$build_alias
+test -z "$ac_cv_build_alias" &&
+  ac_cv_build_alias=`$ac_config_guess`
+test -z "$ac_cv_build_alias" &&
+  { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+   { (exit 1); exit 1; }; }
+ac_cv_build=`$ac_config_sub $ac_cv_build_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6
+build=$ac_cv_build
+build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6
+if test "${ac_cv_host+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_host_alias=$host_alias
+test -z "$ac_cv_host_alias" &&
+  ac_cv_host_alias=$ac_cv_build_alias
+ac_cv_host=`$ac_config_sub $ac_cv_host_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6
+host=$ac_cv_host
+host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+
+case "$host_cpu" in
+  i[3456]86) host_cpu=i386 ;;
+  *) { { echo "$as_me:$LINENO: error: unsupported CPU type" >&5
+echo "$as_me: error: unsupported CPU type" >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+
+case "$host_cpu"-"$host_vendor" in
+  i386-*) host_vendor=pc ;;
+  *) { { echo "$as_me:$LINENO: error: unsupported machine type" >&5
+echo "$as_me: error: unsupported machine type" >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+
+
+
+
+# Checks for programs.
+if test "x$CFLAGS" = x; then
+  default_CFLAGS=yes
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    set dummy "$as_dir/$ac_word" ${1+"$@"}
+    shift
+    ac_cv_prog_CC="$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CC" && break
+done
+
+  CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH" >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH" >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output" >&5
+echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+  (eval $ac_link_default) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Find the output, starting from the most likely.  This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+for ac_file in `ls a_out.exe a.exe conftest.exe 2>/dev/null;
+                ls a.out conftest 2>/dev/null;
+                ls a.* conftest.* 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb | *.xSYM ) ;;
+    a.out ) # We found the default executable, but exeext='' is most
+            # certainly right.
+            break;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+          # FIXME: I believe we export ac_cv_exeext for Libtool --akim.
+          export ac_cv_exeext
+          break;;
+    * ) break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables" >&5
+echo "$as_me: error: C compiler cannot create executables" >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+       cross_compiling=yes
+    else
+       { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in `(ls conftest.exe; ls conftest; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+          export ac_cv_exeext
+          break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link" >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile" >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_compiler_gnu=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+# Some people use a C++ compiler to compile C.  Since we use `exit',
+# in C++ we need to declare it.  In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+  choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  for ac_declaration in \
+   ''\
+   '#include <stdlib.h>' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+$ac_declaration
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+continue
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_declaration
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Must be GCC.
+test "x$GCC" = xyes || { { echo "$as_me:$LINENO: error: GCC is required" >&5
+echo "$as_me: error: GCC is required" >&2;}
+   { (exit 1); exit 1; }; }
+
+if test "x$default_CFLAGS" = xyes; then
+  # debug flags.
+  tmp_CFLAGS="-Wall -W -g"
+
+  # optimization flags.
+  echo "$as_me:$LINENO: checking whether optimization for size works" >&5
+echo $ECHO_N "checking whether optimization for size works... $ECHO_C" >&6
+if test "${size_flag+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+    CFLAGS=-Os
+
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  size_flag=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+size_flag=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+
+fi
+echo "$as_me:$LINENO: result: $size_flag" >&5
+echo "${ECHO_T}$size_flag" >&6
+  if test "x$size_flag" = xyes; then
+    tmp_CFLAGS="$tmp_CFLAGS -Os"
+  else
+    tmp_CFLAGS="$tmp_CFLAGS -O2 -fno-strength-reduce -fno-unroll-loops"
+  fi
+
+  # Force no alignment to save space on i386.
+  if test "x$host_cpu" = xi386; then
+    echo "$as_me:$LINENO: checking whether -falign-loops works" >&5
+echo $ECHO_N "checking whether -falign-loops works... $ECHO_C" >&6
+if test "${falign_loop_flag+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+      CFLAGS="-falign-loops=1"
+      cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  falign_loop_flag=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+falign_loop_flag=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+
+fi
+echo "$as_me:$LINENO: result: $falign_loop_flag" >&5
+echo "${ECHO_T}$falign_loop_flag" >&6
+
+    if test "x$falign_loop_flag" = xyes; then
+      tmp_CFLAGS="$tmp_CFLAGS -falign-jumps=1 -falign-loops=1 -falign-functions=1"
+    else
+      tmp_CFLAGS="$tmp_CFLAGS -malign-jumps=1 -malign-loops=1 -malign-functions=1"
+    fi
+  fi
+
+  CFLAGS="$tmp_CFLAGS"
+fi
+
+
+# Defined in aclocal.m4.
+
+echo "$as_me:$LINENO: checking if C symbols get an underscore after compilation" >&5
+echo $ECHO_N "checking if C symbols get an underscore after compilation... $ECHO_C" >&6
+if test "${pupa_cv_asm_uscore+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat > conftest.c <<\EOF
+int
+func (int *list)
+{
+  *list = 0;
+  return *list;
+}
+EOF
+
+if { ac_try='${CC-cc} ${CFLAGS} -S conftest.c'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } && test -s conftest.s; then
+  true
+else
+  { { echo "$as_me:$LINENO: error: ${CC-cc} failed to produce assembly code" >&5
+echo "$as_me: error: ${CC-cc} failed to produce assembly code" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+if grep _func conftest.s >/dev/null 2>&1; then
+  pupa_cv_asm_uscore=yes
+else
+  pupa_cv_asm_uscore=no
+fi
+
+rm -f conftest*
+fi
+
+
+if test "x$pupa_cv_asm_uscore" = xyes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ASM_USCORE $pupa_cv_asm_uscore
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: result: $pupa_cv_asm_uscore" >&5
+echo "${ECHO_T}$pupa_cv_asm_uscore" >&6
+
+
+echo "$as_me:$LINENO: checking if start is defined by the compiler" >&5
+echo $ECHO_N "checking if start is defined by the compiler... $ECHO_C" >&6
+if test "${pupa_cv_check_start_symbol+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+asm ("incl start")
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  pupa_cv_check_start_symbol=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+pupa_cv_check_start_symbol=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+
+
+echo "$as_me:$LINENO: result: $pupa_cv_check_start_symbol" >&5
+echo "${ECHO_T}$pupa_cv_check_start_symbol" >&6
+
+echo "$as_me:$LINENO: checking if _start is defined by the compiler" >&5
+echo $ECHO_N "checking if _start is defined by the compiler... $ECHO_C" >&6
+if test "${pupa_cv_check_uscore_start_symbol+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+asm ("incl _start")
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  pupa_cv_check_uscore_start_symbol=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+pupa_cv_check_uscore_start_symbol=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+
+
+echo "$as_me:$LINENO: result: $pupa_cv_check_uscore_start_symbol" >&5
+echo "${ECHO_T}$pupa_cv_check_uscore_start_symbol" >&6
+
+
+
+
+if test "x$pupa_cv_check_start_symbol" = xyes; then
+  cat >>confdefs.h <<\_ACEOF
+#define START_SYMBOL start
+_ACEOF
+
+elif test "x$pupa_cv_check_uscore_start_symbol" = xyes; then
+  cat >>confdefs.h <<\_ACEOF
+#define START_SYMBOL _start
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: neither start nor _start is defined" >&5
+echo "$as_me: error: neither start nor _start is defined" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+echo "$as_me:$LINENO: checking if __bss_start is defined by the compiler" >&5
+echo $ECHO_N "checking if __bss_start is defined by the compiler... $ECHO_C" >&6
+if test "${pupa_cv_check_uscore_uscore_bss_start_symbol+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+asm ("incl __bss_start")
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  pupa_cv_check_uscore_uscore_bss_start_symbol=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+pupa_cv_check_uscore_uscore_bss_start_symbol=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+
+
+echo "$as_me:$LINENO: result: $pupa_cv_check_uscore_uscore_bss_start_symbol" >&5
+echo "${ECHO_T}$pupa_cv_check_uscore_uscore_bss_start_symbol" >&6
+
+echo "$as_me:$LINENO: checking if edata is defined by the compiler" >&5
+echo $ECHO_N "checking if edata is defined by the compiler... $ECHO_C" >&6
+if test "${pupa_cv_check_edata_symbol+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+asm ("incl edata")
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  pupa_cv_check_edata_symbol=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+pupa_cv_check_edata_symbol=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+
+
+echo "$as_me:$LINENO: result: $pupa_cv_check_edata_symbol" >&5
+echo "${ECHO_T}$pupa_cv_check_edata_symbol" >&6
+
+echo "$as_me:$LINENO: checking if _edata is defined by the compiler" >&5
+echo $ECHO_N "checking if _edata is defined by the compiler... $ECHO_C" >&6
+if test "${pupa_cv_check_uscore_edata_symbol+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+asm ("incl _edata")
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  pupa_cv_check_uscore_edata_symbol=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+pupa_cv_check_uscore_edata_symbol=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+
+
+echo "$as_me:$LINENO: result: $pupa_cv_check_uscore_edata_symbol" >&5
+echo "${ECHO_T}$pupa_cv_check_uscore_edata_symbol" >&6
+
+
+
+
+if test "x$pupa_cv_check_uscore_uscore_bss_start_symbol" = xyes; then
+  cat >>confdefs.h <<\_ACEOF
+#define BSS_START_SYMBOL __bss_start
+_ACEOF
+
+elif test "x$pupa_cv_check_edata_symbol" = xyes; then
+  cat >>confdefs.h <<\_ACEOF
+#define BSS_START_SYMBOL edata
+_ACEOF
+
+elif test "x$pupa_cv_check_uscore_edata_symbol" = xyes; then
+  cat >>confdefs.h <<\_ACEOF
+#define BSS_START_SYMBOL _edata
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: none of __bss_start, edata or _edata is defined" >&5
+echo "$as_me: error: none of __bss_start, edata or _edata is defined" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+echo "$as_me:$LINENO: checking if end is defined by the compiler" >&5
+echo $ECHO_N "checking if end is defined by the compiler... $ECHO_C" >&6
+if test "${pupa_cv_check_end_symbol+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+asm ("incl end")
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  pupa_cv_check_end_symbol=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+pupa_cv_check_end_symbol=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+
+
+echo "$as_me:$LINENO: result: $pupa_cv_check_end_symbol" >&5
+echo "${ECHO_T}$pupa_cv_check_end_symbol" >&6
+
+echo "$as_me:$LINENO: checking if _end is defined by the compiler" >&5
+echo $ECHO_N "checking if _end is defined by the compiler... $ECHO_C" >&6
+if test "${pupa_cv_check_uscore_end_symbol+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+asm ("incl _end")
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  pupa_cv_check_uscore_end_symbol=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+pupa_cv_check_uscore_end_symbol=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+
+
+echo "$as_me:$LINENO: result: $pupa_cv_check_uscore_end_symbol" >&5
+echo "${ECHO_T}$pupa_cv_check_uscore_end_symbol" >&6
+
+
+
+
+if test "x$pupa_cv_check_end_symbol" = xyes; then
+  cat >>confdefs.h <<\_ACEOF
+#define END_SYMBOL end
+_ACEOF
+
+elif test "x$pupa_cv_check_uscore_end_symbol" = xyes; then
+  cat >>confdefs.h <<\_ACEOF
+#define END_SYMBOL _end
+_ACEOF
+
+else
+  { { echo "$as_me:$LINENO: error: neither end nor _end is defined" >&5
+echo "$as_me: error: neither end nor _end is defined" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+if test "x$host_cpu" = xi386; then
+
+echo "$as_me:$LINENO: checking whether addr32 must be in the same line as the instruction" >&5
+echo $ECHO_N "checking whether addr32 must be in the same line as the instruction... $ECHO_C" >&6
+if test "${pupa_cv_i386_asm_prefix_requirement+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat > conftest.s <<\EOF
+       .code16
+l1:    addr32  movb    %al, l1
+EOF
+
+if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } && test -s conftest.o; then
+  pupa_cv_i386_asm_prefix_requirement=yes
+else
+  pupa_cv_i386_asm_prefix_requirement=no
+fi
+
+rm -f conftest*
+fi
+
+
+if test "x$pupa_cv_i386_asm_prefix_requirement" = xyes; then
+  pupa_tmp_addr32="addr32"
+  pupa_tmp_data32="data32"
+else
+  pupa_tmp_addr32="addr32;"
+  pupa_tmp_data32="data32;"
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define ADDR32 $pupa_tmp_addr32
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define DATA32 $pupa_tmp_data32
+_ACEOF
+
+
+echo "$as_me:$LINENO: result: $pupa_cv_i386_asm_prefix_requirement" >&5
+echo "${ECHO_T}$pupa_cv_i386_asm_prefix_requirement" >&6
+
+
+echo "$as_me:$LINENO: checking for .code16 addr32 assembler support" >&5
+echo $ECHO_N "checking for .code16 addr32 assembler support... $ECHO_C" >&6
+if test "${pupa_cv_i386_asm_addr32+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat > conftest.s.in <<\EOF
+       .code16
+l1:    @ADDR32@        movb    %al, l1
+EOF
+
+if test "x$pupa_cv_i386_asm_prefix_requirement" = xyes; then
+  sed -e s/@ADDR32@/addr32/ < conftest.s.in > conftest.s
+else
+  sed -e s/@ADDR32@/addr32\;/ < conftest.s.in > conftest.s
+fi
+
+if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } && test -s conftest.o; then
+  pupa_cv_i386_asm_addr32=yes
+else
+  pupa_cv_i386_asm_addr32=no
+fi
+
+rm -f conftest*
+fi
+
+
+echo "$as_me:$LINENO: result: $pupa_cv_i386_asm_addr32" >&5
+echo "${ECHO_T}$pupa_cv_i386_asm_addr32" >&6
+
+echo "$as_me:$LINENO: checking whether an absolute indirect call/jump must not be prefixed with an asterisk" >&5
+echo $ECHO_N "checking whether an absolute indirect call/jump must not be prefixed with an asterisk... $ECHO_C" >&6
+if test "${pupa_cv_i386_asm_absolute_without_asterisk+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat > conftest.s <<\EOF
+       lcall   *(offset)
+offset:
+       .long   0
+       .word   0
+EOF
+
+if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } && test -s conftest.o; then
+  pupa_cv_i386_asm_absolute_without_asterisk=no
+else
+  pupa_cv_i386_asm_absolute_without_asterisk=yes
+fi
+
+rm -f conftest*
+fi
+
+
+if test "x$pupa_cv_i386_asm_absolute_without_asterisk" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define ABSOLUTE_WITHOUT_ASTERISK 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: result: $pupa_cv_i386_asm_absolute_without_asterisk" >&5
+echo "${ECHO_T}$pupa_cv_i386_asm_absolute_without_asterisk" >&6
+fi
+
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+        if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+          if test $ac_prog = install &&
+            grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+            # AIX install.  It has an incompatible calling convention.
+            :
+          elif test $ac_prog = install &&
+            grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+            # program-specific install script used by HP pwplus--don't use.
+            :
+          else
+            ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+            break 3
+          fi
+        fi
+      done
+    done
+    ;;
+esac
+done
+
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  We don't cache a
+    # path for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the path is relative.
+    INSTALL=$ac_install_sh
+  fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.make <<\_ACEOF
+all:
+       @echo 'ac_maketemp="${MAKE}"'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+  eval ac_cv_prog_make_${ac_make}_set=yes
+else
+  eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftest.make
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+  SET_MAKE=
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}objcopy", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objcopy; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_OBJCOPY+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$OBJCOPY"; then
+  ac_cv_prog_OBJCOPY="$OBJCOPY" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_OBJCOPY="${ac_tool_prefix}objcopy"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+OBJCOPY=$ac_cv_prog_OBJCOPY
+if test -n "$OBJCOPY"; then
+  echo "$as_me:$LINENO: result: $OBJCOPY" >&5
+echo "${ECHO_T}$OBJCOPY" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_OBJCOPY"; then
+  ac_ct_OBJCOPY=$OBJCOPY
+  # Extract the first word of "objcopy", so it can be a program name with args.
+set dummy objcopy; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_OBJCOPY+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_OBJCOPY"; then
+  ac_cv_prog_ac_ct_OBJCOPY="$ac_ct_OBJCOPY" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_OBJCOPY="objcopy"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_OBJCOPY=$ac_cv_prog_ac_ct_OBJCOPY
+if test -n "$ac_ct_OBJCOPY"; then
+  echo "$as_me:$LINENO: result: $ac_ct_OBJCOPY" >&5
+echo "${ECHO_T}$ac_ct_OBJCOPY" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  OBJCOPY=$ac_ct_OBJCOPY
+else
+  OBJCOPY="$ac_cv_prog_OBJCOPY"
+fi
+
+echo "$as_me:$LINENO: checking whether ${OBJCOPY} works for absolute addresses" >&5
+echo $ECHO_N "checking whether ${OBJCOPY} works for absolute addresses... $ECHO_C" >&6
+if test "${pupa_cv_prog_objcopy_absolute+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat > conftest.c <<\EOF
+void
+cmain (void)
+{
+   *((int *) 0x1000) = 2;
+}
+EOF
+
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && test -s conftest.o; then :
+else
+  { { echo "$as_me:$LINENO: error: ${CC-cc} cannot compile C source code" >&5
+echo "$as_me: error: ${CC-cc} cannot compile C source code" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+pupa_cv_prog_objcopy_absolute=yes
+for link_addr in 2000 8000 7C00; do
+  if { ac_try='${CC-cc} ${CFLAGS} -nostdlib -Wl,-N -Wl,-Ttext -Wl,$link_addr conftest.o -o conftest.exec'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then :
+  else
+    { { echo "$as_me:$LINENO: error: ${CC-cc} cannot link at address $link_addr" >&5
+echo "$as_me: error: ${CC-cc} cannot link at address $link_addr" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  if { ac_try='${OBJCOPY-objcopy} -O binary conftest.exec conftest'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then :
+  else
+    { { echo "$as_me:$LINENO: error: ${OBJCOPY-objcopy} cannot create binary files" >&5
+echo "$as_me: error: ${OBJCOPY-objcopy} cannot create binary files" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  if test ! -f conftest.old || { ac_try='cmp -s conftest.old conftest'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    mv -f conftest conftest.old
+  else
+    pupa_cv_prog_objcopy_absolute=no
+    break
+  fi
+done
+rm -f conftest*
+fi
+
+echo "$as_me:$LINENO: result: $pupa_cv_prog_objcopy_absolute" >&5
+echo "${ECHO_T}$pupa_cv_prog_objcopy_absolute" >&6
+
+if test "x$pupa_cv_prog_objcopy_absolute" = xno; then
+  { { echo "$as_me:$LINENO: error: PUPA requires a working absolute objcopy; upgrade your binutils" >&5
+echo "$as_me: error: PUPA requires a working absolute objcopy; upgrade your binutils" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  STRIP=$ac_ct_STRIP
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}nm", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nm; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_NM+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$NM"; then
+  ac_cv_prog_NM="$NM" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_NM="${ac_tool_prefix}nm"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+NM=$ac_cv_prog_NM
+if test -n "$NM"; then
+  echo "$as_me:$LINENO: result: $NM" >&5
+echo "${ECHO_T}$NM" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_NM"; then
+  ac_ct_NM=$NM
+  # Extract the first word of "nm", so it can be a program name with args.
+set dummy nm; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_NM+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_NM"; then
+  ac_cv_prog_ac_ct_NM="$ac_ct_NM" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_NM="nm"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_NM=$ac_cv_prog_ac_ct_NM
+if test -n "$ac_ct_NM"; then
+  echo "$as_me:$LINENO: result: $ac_ct_NM" >&5
+echo "${ECHO_T}$ac_ct_NM" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  NM=$ac_ct_NM
+else
+  NM="$ac_cv_prog_NM"
+fi
+
+
+# This is not a "must".
+# Extract the first word of "ruby", so it can be a program name with args.
+set dummy ruby; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_RUBY+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $RUBY in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_RUBY="$RUBY" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_RUBY="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  ;;
+esac
+fi
+RUBY=$ac_cv_path_RUBY
+
+if test -n "$RUBY"; then
+  echo "$as_me:$LINENO: result: $RUBY" >&5
+echo "${ECHO_T}$RUBY" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+
+# For cross-compiling.
+if test "x$build" = "x$host"; then
+  BUILD_CC="$CC"
+
+else
+  for ac_prog in gcc egcs cc
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_BUILD_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$BUILD_CC"; then
+  ac_cv_prog_BUILD_CC="$BUILD_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_BUILD_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+BUILD_CC=$ac_cv_prog_BUILD_CC
+if test -n "$BUILD_CC"; then
+  echo "$as_me:$LINENO: result: $BUILD_CC" >&5
+echo "${ECHO_T}$BUILD_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$BUILD_CC" && break
+done
+test -n "$BUILD_CC" || BUILD_CC="{ { echo "$as_me:$LINENO: error: none of gcc, egcs and cc is found. set BUILD_CC manually." >&5
+echo "$as_me: error: none of gcc, egcs and cc is found. set BUILD_CC manually." >&2;}
+   { (exit 1); exit 1; }; }"
+
+fi
+
+# Test the C compiler for the build environment.
+pupa_tmp_CC="$CC"
+CC="$BUILD_CC"
+echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
+echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6
+if test "${ac_cv_c_bigendian+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # See if sys/param.h defines the BYTE_ORDER macro.
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+ bogus endian macros
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_bigendian=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_c_bigendian=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+# It does not; compile a test program.
+if test "$cross_compiling" = yes; then
+  # try to guess the endianess by grep'ing values into an object file
+  ac_cv_c_bigendian=unknown
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
+short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+ _ascii (); _ebcdic ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  if fgrep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
+  ac_cv_c_bigendian=yes
+fi
+if fgrep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+  if test "$ac_cv_c_bigendian" = unknown; then
+    ac_cv_c_bigendian=no
+  else
+    # finding both strings is unlikely to happen, but who knows?
+    ac_cv_c_bigendian=unknown
+  fi
+fi
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+int
+main ()
+{
+  /* Are we little or big endian?  From Harbison&Steele.  */
+  union
+  {
+    long l;
+    char c[sizeof (long)];
+  } u;
+  u.l = 1;
+  exit (u.c[sizeof (long) - 1] == 1);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_bigendian=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+( exit $ac_status )
+ac_cv_c_bigendian=yes
+fi
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
+echo "${ECHO_T}$ac_cv_c_bigendian" >&6
+case $ac_cv_c_bigendian in
+  yes)
+
+cat >>confdefs.h <<\_ACEOF
+#define WORDS_BIGENDIAN 1
+_ACEOF
+ ;;
+  no)
+     ;;
+  *)
+    { { echo "$as_me:$LINENO: error: unknown endianess
+presetting ac_cv_c_bigendian=no (or yes) will help" >&5
+echo "$as_me: error: unknown endianess
+presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <assert.h>
+                     Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <assert.h>
+                     Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check" >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  egrep -v '^ *\+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_cv_header_stdc=yes
+else
+  echo "$as_me: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) (('a' <= (c) && (c) <= 'i') \
+                     || ('j' <= (c) && (c) <= 'r') \
+                     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+        || toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                  inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  eval "$as_ac_Header=yes"
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+echo "$as_me:$LINENO: checking for void *" >&5
+echo $ECHO_N "checking for void *... $ECHO_C" >&6
+if test "${ac_cv_type_void_p+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+if ((void * *) 0)
+  return 0;
+if (sizeof (void *))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_void_p=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_type_void_p=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_void_p" >&5
+echo "${ECHO_T}$ac_cv_type_void_p" >&6
+
+echo "$as_me:$LINENO: checking size of void *" >&5
+echo $ECHO_N "checking size of void *... $ECHO_C" >&6
+if test "${ac_cv_sizeof_void_p+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$ac_cv_type_void_p" = yes; then
+  # The cast to unsigned long works around a bug in the HP C Compiler
+  # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+  # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+  # This bug is HP SR number 8606223364.
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (void *))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (void *))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_lo=`expr $ac_mid + 1`
+                    if test $ac_lo -le $ac_mid; then
+                      ac_lo= ac_hi=
+                      break
+                    fi
+                    ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (void *))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (void *))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_hi=`expr '(' $ac_mid ')' - 1`
+                       if test $ac_mid -le $ac_hi; then
+                         ac_lo= ac_hi=
+                         break
+                       fi
+                       ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_lo= ac_hi=
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (void *))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_void_p=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (void *), 77" >&5
+echo "$as_me: error: cannot compute sizeof (void *), 77" >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+else
+  if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling" >&5
+echo "$as_me: error: cannot run test program while cross compiling" >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+long longval () { return (long) (sizeof (void *)); }
+unsigned long ulongval () { return (long) (sizeof (void *)); }
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    exit (1);
+  if (((long) (sizeof (void *))) < 0)
+    {
+      long i = longval ();
+      if (i != ((long) (sizeof (void *))))
+       exit (1);
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long i = ulongval ();
+      if (i != ((long) (sizeof (void *))))
+       exit (1);
+      fprintf (f, "%lu\n", i);
+    }
+  exit (ferror (f) || fclose (f) != 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_void_p=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (void *), 77" >&5
+echo "$as_me: error: cannot compute sizeof (void *), 77" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+  ac_cv_sizeof_void_p=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_void_p" >&5
+echo "${ECHO_T}$ac_cv_sizeof_void_p" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking for long" >&5
+echo $ECHO_N "checking for long... $ECHO_C" >&6
+if test "${ac_cv_type_long+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+if ((long *) 0)
+  return 0;
+if (sizeof (long))
+  return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_long=yes
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_type_long=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_long" >&5
+echo "${ECHO_T}$ac_cv_type_long" >&6
+
+echo "$as_me:$LINENO: checking size of long" >&5
+echo $ECHO_N "checking size of long... $ECHO_C" >&6
+if test "${ac_cv_sizeof_long+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$ac_cv_type_long" = yes; then
+  # The cast to unsigned long works around a bug in the HP C Compiler
+  # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+  # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+  # This bug is HP SR number 8606223364.
+  if test "$cross_compiling" = yes; then
+  # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) >= 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_lo=`expr $ac_mid + 1`
+                    if test $ac_lo -le $ac_mid; then
+                      ac_lo= ac_hi=
+                      break
+                    fi
+                    ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) < 0)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) >= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_lo=$ac_mid; break
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_hi=`expr '(' $ac_mid ')' - 1`
+                       if test $ac_mid -le $ac_hi; then
+                         ac_lo= ac_hi=
+                         break
+                       fi
+                       ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_lo= ac_hi=
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)];
+test_array [0] = 0
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_hi=$ac_mid
+else
+  echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_long=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77" >&5
+echo "$as_me: error: cannot compute sizeof (long), 77" >&2;}
+   { (exit 1); exit 1; }; } ;;
+esac
+else
+  if test "$cross_compiling" = yes; then
+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling" >&5
+echo "$as_me: error: cannot run test program while cross compiling" >&2;}
+   { (exit 1); exit 1; }; }
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+long longval () { return (long) (sizeof (long)); }
+unsigned long ulongval () { return (long) (sizeof (long)); }
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef F77_DUMMY_MAIN
+#  ifdef __cplusplus
+     extern "C"
+#  endif
+   int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    exit (1);
+  if (((long) (sizeof (long))) < 0)
+    {
+      long i = longval ();
+      if (i != ((long) (sizeof (long))))
+       exit (1);
+      fprintf (f, "%ld\n", i);
+    }
+  else
+    {
+      unsigned long i = ulongval ();
+      if (i != ((long) (sizeof (long))))
+       exit (1);
+      fprintf (f, "%lu\n", i);
+    }
+  exit (ferror (f) || fclose (f) != 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sizeof_long=`cat conftest.val`
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77" >&5
+echo "$as_me: error: cannot compute sizeof (long), 77" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+  ac_cv_sizeof_long=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5
+echo "${ECHO_T}$ac_cv_sizeof_long" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+_ACEOF
+
+
+CC="$pupa_tmp_CC"
+
+# Output files.
+ac_config_links="$ac_config_links include/pupa/cpu:include/pupa/$host_cpu include/pupa/machine:include/pupa/$host_cpu/$host_vendor"
+
+ac_config_files="$ac_config_files Makefile"
+
+ac_config_files="$ac_config_files stamp-h"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overriden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+  (set) 2>&1 |
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+        "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;;
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n \
+        "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      ;;
+    esac;
+} |
+  sed '
+     t clear
+     : clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if cmp -s $cache_file confcache; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+    cat confcache >$cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[        ]*VPATH[        ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[   ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[     ]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
+fi
+
+# NLS nuisances.
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+(set +x; test -n "`(LANG=C; export LANG) 2>&1`") &&
+    { $as_unset LANG || test "${LANG+set}" != set; } ||
+      { LANG=C; export LANG; }
+(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") &&
+    { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } ||
+      { LC_ALL=C; export LC_ALL; }
+(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") &&
+    { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } ||
+      { LC_TIME=C; export LC_TIME; }
+(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") &&
+    { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } ||
+      { LC_CTYPE=C; export LC_CTYPE; }
+(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") &&
+    { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } ||
+      { LANGUAGE=C; export LANGUAGE; }
+(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") &&
+    { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } ||
+      { LC_COLLATE=C; export LC_COLLATE; }
+(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") &&
+    { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } ||
+      { LC_NUMERIC=C; export LC_NUMERIC; }
+(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") &&
+    { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } ||
+      { LC_MESSAGES=C; export LC_MESSAGES; }
+
+
+# Name of the executable.
+as_me=`(basename "$0") 2>/dev/null ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)$' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+         /^X\/\(\/\/\)$/{ s//\1/; q; }
+         /^X\/\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conftest.sh
+  echo  "exit 0"   >>conftest.sh
+  chmod +x conftest.sh
+  if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conftest.sh
+fi
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+        case $as_dir in
+        /*)
+          if ("$as_dir/$as_base" -c '
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+            CONFIG_SHELL=$as_dir/$as_base
+            export CONFIG_SHELL
+            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+          fi;;
+        esac
+       done
+done
+;;
+  esac
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
+    sed '
+      N
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      t loop
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
+    ' >$as_me.lineno &&
+  chmod +x $as_me.lineno ||
+    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
+  # Exit status is that of the last command.
+  exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='     ' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
+    as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+  as_ln_s=ln
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS="  $as_nl"
+
+# CDPATH.
+$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; }
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.  Logging --version etc. is OK.
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by PUPA $as_me 0.6, which was
+generated by GNU Autoconf 2.53.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number, then exit
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+  --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+  --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration links:
+$config_links
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+PUPA config.status 0.6
+configured by $0, generated by GNU Autoconf 2.53,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value.  By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "x$1" : 'x\([^=]*\)='`
+    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+    shift
+    set dummy "$ac_option" "$ac_optarg" ${1+"$@"}
+    shift
+    ;;
+  -*);;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_need_defaults=false;;
+  esac
+
+  case $1 in
+  # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running $SHELL $0 " $ac_configure_args " --no-create --no-recursion"
+    exec $SHELL $0 $ac_configure_args --no-create --no-recursion ;;
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit 0 ;;
+  --debug | --d* | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    shift
+    CONFIG_FILES="$CONFIG_FILES $1"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    shift
+    CONFIG_HEADERS="$CONFIG_HEADERS $1"
+    ac_need_defaults=false;;
+
+  # This is an error.
+  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1" ;;
+
+  esac
+  shift
+done
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+  case "$ac_config_target" in
+  # Handling of arguments.
+  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  "stamp-h" ) CONFIG_FILES="$CONFIG_FILES stamp-h" ;;
+  "include/pupa/cpu" ) CONFIG_LINKS="$CONFIG_LINKS include/pupa/cpu:include/pupa/$host_cpu" ;;
+  "include/pupa/machine" ) CONFIG_LINKS="$CONFIG_LINKS include/pupa/machine:include/pupa/$host_cpu/$host_vendor" ;;
+  "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_LINKS+set}" = set || CONFIG_LINKS=$config_links
+fi
+
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+: ${TMPDIR=/tmp}
+{
+  tmp=`(umask 077 && mktemp -d -q "$TMPDIR/csXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=$TMPDIR/cs$$-$RANDOM
+  (umask 077 && mkdir $tmp)
+} ||
+{
+   echo "$me: cannot create a temporary directory in $TMPDIR" >&2
+   { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+  # Protect against being on the right side of a sed subst in config.status.
+  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@build@,$build,;t t
+s,@build_cpu@,$build_cpu,;t t
+s,@build_vendor@,$build_vendor,;t t
+s,@build_os@,$build_os,;t t
+s,@host@,$host,;t t
+s,@host_cpu@,$host_cpu,;t t
+s,@host_vendor@,$host_vendor,;t t
+s,@host_os@,$host_os,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@SET_MAKE@,$SET_MAKE,;t t
+s,@OBJCOPY@,$OBJCOPY,;t t
+s,@ac_ct_OBJCOPY@,$ac_ct_OBJCOPY,;t t
+s,@STRIP@,$STRIP,;t t
+s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t
+s,@NM@,$NM,;t t
+s,@ac_ct_NM@,$ac_ct_NM,;t t
+s,@RUBY@,$RUBY,;t t
+s,@BUILD_CC@,$BUILD_CC,;t t
+s,@CPP@,$CPP,;t t
+CEOF
+
+_ACEOF
+
+  cat >>$CONFIG_STATUS <<\_ACEOF
+  # Split the substitutions into bite-sized pieces for seds with
+  # small command number limits, like on Digital OSF/1 and HP-UX.
+  ac_max_sed_lines=48
+  ac_sed_frag=1 # Number of current file.
+  ac_beg=1 # First line for current file.
+  ac_end=$ac_max_sed_lines # Line after last line for current file.
+  ac_more_lines=:
+  ac_sed_cmds=
+  while $ac_more_lines; do
+    if test $ac_beg -gt 1; then
+      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    else
+      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    fi
+    if test ! -s $tmp/subs.frag; then
+      ac_more_lines=false
+    else
+      # The purpose of the label and of the branching condition is to
+      # speed up the sed processing (if there are no `@' at all, there
+      # is no need to browse any of the substitutions).
+      # These are the two extra sed commands mentioned above.
+      (echo ':t
+  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+      if test -z "$ac_sed_cmds"; then
+       ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+      else
+       ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+      fi
+      ac_sed_frag=`expr $ac_sed_frag + 1`
+      ac_beg=$ac_end
+      ac_end=`expr $ac_end + $ac_max_sed_lines`
+    fi
+  done
+  if test -z "$ac_sed_cmds"; then
+    ac_sed_cmds=cat
+  fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+        cat >$tmp/stdin
+        ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+        ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+        ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$ac_file" : 'X\(//\)[^/]' \| \
+         X"$ac_file" : 'X\(//\)$' \| \
+         X"$ac_file" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  { case "$ac_dir" in
+  [\\/]* | ?:[\\/]* ) as_incr_dir=;;
+  *)                      as_incr_dir=.;;
+esac
+as_dummy="$ac_dir"
+for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do
+  case $as_mkdir_dir in
+    # Skip DOS drivespec
+    ?:) as_incr_dir=$as_mkdir_dir ;;
+    *)
+      as_incr_dir=$as_incr_dir/$as_mkdir_dir
+      test -d "$as_incr_dir" ||
+        mkdir "$as_incr_dir" ||
+       { { echo "$as_me:$LINENO: error: cannot create \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }
+    ;;
+  esac
+done; }
+
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+# absolute.
+ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+ac_abs_top_builddir=`cd "$ac_dir" && cd $ac_top_builddir && pwd`
+ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+  esac
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    configure_input=
+  else
+    configure_input="$ac_file.  "
+  fi
+  configure_input=$configure_input"Generated from `echo $ac_file_in |
+                                     sed 's,.*/,,'` by configure."
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+         # Absolute (can't be DOS-style, as IFS=:)
+         test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+         echo $f;;
+      *) # Relative
+         if test -f "$f"; then
+           # Build tree
+           echo $f
+         elif test -f "$srcdir/$f"; then
+           # Source tree
+           echo $srcdir/$f
+         else
+           # /dev/null tree
+           { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+         fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+s,@INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+  rm -f $tmp/stdin
+  if test x"$ac_file" != x-; then
+    mv $tmp/out $ac_file
+  else
+    cat $tmp/out
+    rm -f $tmp/out
+  fi
+
+  # Run the commands associated with the file.
+  case $ac_file in
+    stamp-h ) echo timestamp > stamp-h ;;
+  esac
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([  ]*\)#\([        ]*define[       ][      ]*\)'
+ac_dB='[       ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+        cat >$tmp/stdin
+        ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+        ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+        ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+         # Absolute (can't be DOS-style, as IFS=:)
+         test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+         echo $f;;
+      *) # Relative
+         if test -f "$f"; then
+           # Build tree
+           echo $f
+         elif test -f "$srcdir/$f"; then
+           # Source tree
+           echo $srcdir/$f
+         else
+           # /dev/null tree
+           { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+         fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+  # Remove the trailing spaces.
+  sed 's/[     ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h.  The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status.  Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[   ]*#[    ]*define[       ][      ]*\([^  (][^    (]*\)\(([^)]*)\)[       ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[   ]*#[    ]*define[       ][      ]*\([^  ][^     ]*\)[   ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless.  Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[   ]*#[    ]*undef[        ][      ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo '  if egrep "^[   ]*#[    ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo '  # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo '  :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+  # Write a limited-size here document to $tmp/defines.sed.
+  echo '  cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#define' lines.
+  echo '/^[    ]*#[    ]*define/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/defines.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+  rm -f conftest.defines
+  mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo '  fi # egrep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+  # Write a limited-size here document to $tmp/undefs.sed.
+  echo '  cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#undef'
+  echo '/^[    ]*#[    ]*undef/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+  rm -f conftest.undefs
+  mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    echo "/* Generated by configure.  */" >$tmp/config.h
+  else
+    echo "/* $ac_file.  Generated by configure.  */" >$tmp/config.h
+  fi
+  cat $tmp/in >>$tmp/config.h
+  rm -f $tmp/in
+  if test x"$ac_file" != x-; then
+    if cmp -s $ac_file $tmp/config.h 2>/dev/null; then
+      { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$ac_file" : 'X\(//\)[^/]' \| \
+         X"$ac_file" : 'X\(//\)$' \| \
+         X"$ac_file" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+      { case "$ac_dir" in
+  [\\/]* | ?:[\\/]* ) as_incr_dir=;;
+  *)                      as_incr_dir=.;;
+esac
+as_dummy="$ac_dir"
+for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do
+  case $as_mkdir_dir in
+    # Skip DOS drivespec
+    ?:) as_incr_dir=$as_mkdir_dir ;;
+    *)
+      as_incr_dir=$as_incr_dir/$as_mkdir_dir
+      test -d "$as_incr_dir" ||
+        mkdir "$as_incr_dir" ||
+       { { echo "$as_me:$LINENO: error: cannot create \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }
+    ;;
+  esac
+done; }
+
+      rm -f $ac_file
+      mv $tmp/config.h $ac_file
+    fi
+  else
+    cat $tmp/config.h
+    rm -f $tmp/config.h
+  fi
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_LINKS section.
+#
+
+for ac_file in : $CONFIG_LINKS; do test "x$ac_file" = x: && continue
+  ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
+  ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
+
+  { echo "$as_me:$LINENO: linking $srcdir/$ac_source to $ac_dest" >&5
+echo "$as_me: linking $srcdir/$ac_source to $ac_dest" >&6;}
+
+  if test ! -r $srcdir/$ac_source; then
+    { { echo "$as_me:$LINENO: error: $srcdir/$ac_source: file not found" >&5
+echo "$as_me: error: $srcdir/$ac_source: file not found" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  rm -f $ac_dest
+
+  # Make relative symlinks.
+  ac_dest_dir=`(dirname "$ac_dest") 2>/dev/null ||
+$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+         X"$ac_dest" : 'X\(//\)[^/]' \| \
+         X"$ac_dest" : 'X\(//\)$' \| \
+         X"$ac_dest" : 'X\(/\)' \| \
+         .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_dest" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  { case "$ac_dest_dir" in
+  [\\/]* | ?:[\\/]* ) as_incr_dir=;;
+  *)                      as_incr_dir=.;;
+esac
+as_dummy="$ac_dest_dir"
+for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do
+  case $as_mkdir_dir in
+    # Skip DOS drivespec
+    ?:) as_incr_dir=$as_mkdir_dir ;;
+    *)
+      as_incr_dir=$as_incr_dir/$as_mkdir_dir
+      test -d "$as_incr_dir" ||
+        mkdir "$as_incr_dir" ||
+       { { echo "$as_me:$LINENO: error: cannot create \"$ac_dest_dir\"" >&5
+echo "$as_me: error: cannot create \"$ac_dest_dir\"" >&2;}
+   { (exit 1); exit 1; }; }
+    ;;
+  esac
+done; }
+
+  ac_builddir=.
+
+if test "$ac_dest_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dest_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+# Don't blindly perform a `cd "$ac_dest_dir"/$ac_foo && pwd` since $ac_foo can be
+# absolute.
+ac_abs_builddir=`cd "$ac_dest_dir" && cd $ac_builddir && pwd`
+ac_abs_top_builddir=`cd "$ac_dest_dir" && cd $ac_top_builddir && pwd`
+ac_abs_srcdir=`cd "$ac_dest_dir" && cd $ac_srcdir && pwd`
+ac_abs_top_srcdir=`cd "$ac_dest_dir" && cd $ac_top_srcdir && pwd`
+
+
+  case $srcdir in
+  [\\/$]* | ?:[\\/]* ) ac_rel_source=$srcdir/$ac_source ;;
+      *) ac_rel_source=$ac_top_builddir$srcdir/$ac_source ;;
+  esac
+
+  # Make a symlink if possible; otherwise try a hard link.
+  ln -s $ac_rel_source $ac_dest 2>/dev/null ||
+    ln $srcdir/$ac_source $ac_dest ||
+    { { echo "$as_me:$LINENO: error: cannot link $ac_dest to $srcdir/$ac_source" >&5
+echo "$as_me: error: cannot link $ac_dest to $srcdir/$ac_source" >&2;}
+   { (exit 1); exit 1; }; }
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..524fc14
--- /dev/null
@@ -0,0 +1,124 @@
+# Process this file with autoconf to produce a configure script.
+
+# Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+#
+# This configure.ac is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+AC_INIT(PUPA, 0.6, [okuji@enbug.org])
+AC_PREREQ(2.53)
+AC_CONFIG_SRCDIR([include/pupa/dl.h])
+AC_CONFIG_HEADER([config.h])
+
+# Checks for build and host systems.
+AC_CANONICAL_BUILD
+AC_CANONICAL_HOST
+
+case "$host_cpu" in
+  i[[3456]]86) host_cpu=i386 ;;
+  *) AC_MSG_ERROR([unsupported CPU type]) ;;
+esac
+
+case "$host_cpu"-"$host_vendor" in
+  i386-*) host_vendor=pc ;;
+  *) AC_MSG_ERROR([unsupported machine type]) ;;
+esac
+
+AC_SUBST(host_cpu)
+AC_SUBST(host_vendor)
+
+# Checks for programs.
+if test "x$CFLAGS" = x; then
+  default_CFLAGS=yes
+fi
+
+AC_PROG_CC
+
+# Must be GCC.
+test "x$GCC" = xyes || AC_MSG_ERROR([GCC is required])
+
+if test "x$default_CFLAGS" = xyes; then
+  # debug flags.
+  tmp_CFLAGS="-Wall -W -g"
+
+  # optimization flags.
+  AC_CACHE_CHECK([whether optimization for size works], size_flag, [
+    CFLAGS=-Os
+    AC_TRY_COMPILE(, , size_flag=yes, size_flag=no)
+  ])
+  if test "x$size_flag" = xyes; then
+    tmp_CFLAGS="$tmp_CFLAGS -Os"
+  else
+    tmp_CFLAGS="$tmp_CFLAGS -O2 -fno-strength-reduce -fno-unroll-loops"
+  fi
+
+  # Force no alignment to save space on i386.
+  if test "x$host_cpu" = xi386; then
+    AC_CACHE_CHECK([whether -falign-loops works], [falign_loop_flag], [
+      CFLAGS="-falign-loops=1"
+      AC_TRY_COMPILE(, , [falign_loop_flag=yes], [falign_loop_flag=no])
+    ])
+
+    if test "x$falign_loop_flag" = xyes; then
+      tmp_CFLAGS="$tmp_CFLAGS -falign-jumps=1 -falign-loops=1 -falign-functions=1"
+    else
+      tmp_CFLAGS="$tmp_CFLAGS -malign-jumps=1 -malign-loops=1 -malign-functions=1"
+    fi
+  fi
+
+  CFLAGS="$tmp_CFLAGS"
+fi
+AC_SUBST(CFLAGS)
+
+# Defined in aclocal.m4.
+pupa_ASM_USCORE
+pupa_CHECK_START_SYMBOL
+pupa_CHECK_BSS_START_SYMBOL
+pupa_CHECK_END_SYMBOL
+
+if test "x$host_cpu" = xi386; then
+  pupa_I386_ASM_PREFIX_REQUIREMENT
+  pupa_I386_ASM_ADDR32
+  pupa_I386_ASM_ABSOLUTE_WITHOUT_ASTERISK
+fi
+
+
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+AC_CHECK_TOOL(OBJCOPY, objcopy)
+pupa_PROG_OBJCOPY_ABSOLUTE
+AC_CHECK_TOOL(STRIP, strip)
+AC_CHECK_TOOL(NM, nm)
+
+# This is not a "must".
+AC_PATH_PROG(RUBY, ruby)
+
+# For cross-compiling.
+if test "x$build" = "x$host"; then
+  BUILD_CC="$CC"
+  AC_SUBST(BUILD_CC)
+else
+  AC_CHECK_PROGS(BUILD_CC, [gcc egcs cc],
+                [AC_MSG_ERROR([none of gcc, egcs and cc is found. set BUILD_CC manually.])])
+fi
+
+# Test the C compiler for the build environment.
+pupa_tmp_CC="$CC"
+CC="$BUILD_CC"
+AC_C_BIGENDIAN
+AC_CHECK_SIZEOF(void *)
+AC_CHECK_SIZEOF(long)
+CC="$pupa_tmp_CC"
+
+# Output files.
+AC_CONFIG_LINKS([include/pupa/cpu:include/pupa/$host_cpu
+       include/pupa/machine:include/pupa/$host_cpu/$host_vendor])
+AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([stamp-h], [echo timestamp > stamp-h])
+AC_OUTPUT
diff --git a/disk/i386/pc/biosdisk.c b/disk/i386/pc/biosdisk.c
new file mode 100644 (file)
index 0000000..af14c10
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 1999,2000,2001,2002  Free Software Foundation, Inc.
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/machine/biosdisk.h>
+#include <pupa/machine/memory.h>
+#include <pupa/disk.h>
+#include <pupa/mm.h>
+#include <pupa/types.h>
+#include <pupa/misc.h>
+#include <pupa/err.h>
+#include <pupa/term.h>
+
+/* Drive Parameters.  */
+struct pupa_biosdisk_drp
+{
+  pupa_uint16_t size;
+  pupa_uint16_t flags;
+  pupa_uint32_t cylinders;
+  pupa_uint32_t heads;
+  pupa_uint32_t sectors;
+  pupa_uint64_t total_sectors;
+  pupa_uint16_t bytes_per_sector;
+  /* ver 2.0 or higher */
+  pupa_uint32_t EDD_configuration_parameters;
+  /* ver 3.0 or higher */
+  pupa_uint16_t signature_dpi;
+  pupa_uint8_t length_dpi;
+  pupa_uint8_t reserved[3];
+  pupa_uint8_t name_of_host_bus[4];
+  pupa_uint8_t name_of_interface_type[8];
+  pupa_uint8_t interface_path[8];
+  pupa_uint8_t device_path[8];
+  pupa_uint8_t reserved2;
+  pupa_uint8_t checksum;
+  
+  /* XXX: This is necessary, because the BIOS of Thinkpad X20
+     writes a garbage to the tail of drive parameters,
+     regardless of a size specified in a caller.  */
+  pupa_uint8_t dummy[16];
+} __attribute__ ((packed));
+
+/* Disk Address Packet.  */
+struct pupa_biosdisk_dap
+{
+  pupa_uint8_t length;
+  pupa_uint8_t reserved;
+  pupa_uint16_t blocks;
+  pupa_uint32_t buffer;
+  pupa_uint64_t block;
+} __attribute__ ((packed));
+
+
+static int
+pupa_biosdisk_get_drive (const char *name)
+{
+  unsigned long drive;
+
+  if ((name[0] != 'f' && name[0] != 'h') || name[1] != 'd')
+    goto fail;
+    
+  drive = pupa_strtoul (name + 2, 0, 10);
+  if (pupa_errno != PUPA_ERR_NONE)
+    goto fail;
+
+  if (name[0] == 'h')
+    drive += 0x80;
+  
+  return (int) drive ;
+
+ fail:
+  pupa_error (PUPA_ERR_UNKNOWN_DEVICE, "not a biosdisk");
+  return -1;
+}
+
+static int
+pupa_biosdisk_call_hook (int (*hook) (const char *name), int drive)
+{
+  char name[4];
+
+  pupa_sprintf (name, (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80));
+  return hook (name);
+}
+
+static int
+pupa_biosdisk_iterate (int (*hook) (const char *name))
+{
+  int drive;
+  int num_floppies;
+
+  /* For floppy disks, we can get the number safely.  */
+  num_floppies = pupa_biosdisk_get_num_floppies ();
+  for (drive = 0; drive < num_floppies; drive++)
+    if (pupa_biosdisk_call_hook (hook, drive))
+      return 1;
+  
+  /* For hard disks, attempt to read the MBR.  */
+  for (drive = 0x80; drive < 0x88; drive++)
+    {
+      if (pupa_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
+                                    PUPA_MEMORY_MACHINE_SCRATCH_SEG) != 0)
+       break;
+      
+      if (pupa_biosdisk_call_hook (hook, drive))
+       return 1;
+    }
+  
+  return 0;
+}
+
+static pupa_err_t
+pupa_biosdisk_open (const char *name, pupa_disk_t disk)
+{
+  unsigned long total_sectors = 0;
+  int drive;
+  struct pupa_biosdisk_data *data;
+
+  drive = pupa_biosdisk_get_drive (name);
+  if (drive < 0)
+    return pupa_errno;
+
+  disk->has_partitions = (drive & 0x80);
+  disk->id = drive;
+  
+  data = (struct pupa_biosdisk_data *) pupa_malloc (sizeof (*data));
+  if (! data)
+    return pupa_errno;
+  
+  data->drive = drive;
+  data->flags = 0;
+  
+  if (drive & 0x80)
+    {
+      /* HDD */
+      int version;
+      
+      version = pupa_biosdisk_check_int13_extensions (drive);
+      if (version)
+       {
+         struct pupa_biosdisk_drp *drp
+           = (struct pupa_biosdisk_drp *) PUPA_MEMORY_MACHINE_SCRATCH_ADDR;
+
+         /* Clear out the DRP.  */
+         pupa_memset (drp, 0, sizeof (*drp));
+         drp->size = sizeof (*drp);
+         if (pupa_biosdisk_get_diskinfo_int13_extensions (drive, drp))
+           {
+             data->flags = PUPA_BIOSDISK_FLAG_LBA;
+
+             /* FIXME: 2TB limit.  */
+             if (drp->total_sectors)
+               total_sectors = drp->total_sectors & ~0L;
+             else
+                /* Some buggy BIOSes doesn't return the total sectors
+                   correctly but returns zero. So if it is zero, compute
+                   it by C/H/S returned by the LBA BIOS call.  */
+                total_sectors = drp->cylinders * drp->heads * drp->sectors;
+           }
+       }
+    }
+
+  if (pupa_biosdisk_get_diskinfo_standard (drive,
+                                          &data->cylinders,
+                                          &data->heads,
+                                          &data->sectors) != 0)
+    {
+      pupa_free (data);
+      return pupa_error (PUPA_ERR_BAD_DEVICE, "cannot get C/H/S values");
+    }
+
+  if (! total_sectors)
+    total_sectors = data->cylinders * data->heads * data->sectors;
+
+  disk->total_sectors = total_sectors;
+  disk->data = data;
+  
+  return PUPA_ERR_NONE;
+}
+
+static void
+pupa_biosdisk_close (pupa_disk_t disk)
+{
+  pupa_free (disk->data);
+}
+
+/* For readability.  */
+#define PUPA_BIOSDISK_READ     0
+#define PUPA_BIOSDISK_WRITE    1
+
+static pupa_err_t
+pupa_biosdisk_rw (int cmd, pupa_disk_t disk,
+                 unsigned long sector, unsigned long size,
+                 unsigned segment)
+{
+  struct pupa_biosdisk_data *data = disk->data;
+  
+  if (data->flags & PUPA_BIOSDISK_FLAG_LBA)
+    {
+      struct pupa_biosdisk_dap *dap;
+      
+      dap = (struct pupa_biosdisk_dap *) (PUPA_MEMORY_MACHINE_SCRATCH_ADDR
+                                         + (data->sectors
+                                            << PUPA_DISK_SECTOR_BITS));
+      dap->length = sizeof (*dap);
+      dap->reserved = 0;
+      dap->blocks = size;
+      dap->buffer = segment << 16;     /* The format SEGMENT:ADDRESS.  */
+      dap->block = sector;
+
+      if (pupa_biosdisk_rw_int13_extensions (cmd + 0x42, data->drive, dap))
+       {
+         /* Fall back to the CHS mode.  */
+         data->flags &= ~PUPA_BIOSDISK_FLAG_LBA;
+         disk->total_sectors = data->cylinders * data->heads * data->sectors;
+         return pupa_biosdisk_rw (cmd, disk, sector, size, segment);
+       }
+    }
+  else
+    {
+      unsigned coff, hoff, soff;
+      unsigned head;
+      
+      soff = sector % data->sectors + 1;
+      head = sector / data->sectors;
+      hoff = head % data->heads;
+      coff = head / data->heads;
+
+      if (coff >= data->cylinders)
+       return pupa_error (PUPA_ERR_OUT_OF_RANGE, "out of disk");
+
+      if (pupa_biosdisk_rw_standard (cmd + 0x02, data->drive,
+                                    coff, hoff, soff, size, segment))
+       {
+         switch (cmd)
+           {
+           case PUPA_BIOSDISK_READ:
+             return pupa_error (PUPA_ERR_READ_ERROR, "biosdisk read error");
+           case PUPA_BIOSDISK_WRITE:
+             return pupa_error (PUPA_ERR_WRITE_ERROR, "biosdisk write error");
+           }
+       }
+    }
+
+  return PUPA_ERR_NONE;
+}
+
+static pupa_err_t
+pupa_biosdisk_read (pupa_disk_t disk, unsigned long sector,
+                   unsigned long size, char *buf)
+{
+  struct pupa_biosdisk_data *data = disk->data;
+
+  while (size)
+    {
+      unsigned long len;
+
+      len = data->sectors - (sector % data->sectors);
+      if (len > size)
+       len = size;
+
+      if (pupa_biosdisk_rw (PUPA_BIOSDISK_READ, disk, sector, len,
+                           PUPA_MEMORY_MACHINE_SCRATCH_SEG))
+       return pupa_errno;
+
+      pupa_memcpy (buf, (void *) PUPA_MEMORY_MACHINE_SCRATCH_ADDR,
+                  len << PUPA_DISK_SECTOR_BITS);
+      buf += len << PUPA_DISK_SECTOR_BITS;
+      sector += len;
+      size -= len;
+    }
+
+  return pupa_errno;
+}
+
+static pupa_err_t
+pupa_biosdisk_write (pupa_disk_t disk, unsigned long sector,
+                    unsigned long size, const char *buf)
+{
+  struct pupa_biosdisk_data *data = disk->data;
+
+  while (size)
+    {
+      unsigned long len;
+
+      len = data->sectors - (sector % data->sectors);
+      if (len > size)
+       len = size;
+
+      pupa_memcpy ((void *) PUPA_MEMORY_MACHINE_SCRATCH_ADDR, buf,
+                  len << PUPA_DISK_SECTOR_BITS);
+
+      if (pupa_biosdisk_rw (PUPA_BIOSDISK_WRITE, disk, sector, len,
+                           PUPA_MEMORY_MACHINE_SCRATCH_SEG))
+       return pupa_errno;
+
+      buf += len << PUPA_DISK_SECTOR_BITS;
+      sector += len;
+      size -= len;
+    }
+
+  return pupa_errno;
+}
+
+static struct pupa_disk_dev pupa_biosdisk_dev =
+  {
+    .name = "biosdisk",
+    .iterate = pupa_biosdisk_iterate,
+    .open = pupa_biosdisk_open,
+    .close = pupa_biosdisk_close,
+    .read = pupa_biosdisk_read,
+    .write = pupa_biosdisk_write,
+    .next = 0
+  };
+
+void
+pupa_biosdisk_init (void)
+{
+  pupa_disk_dev_register (&pupa_biosdisk_dev);
+}
diff --git a/disk/i386/pc/partition.c b/disk/i386/pc/partition.c
new file mode 100644 (file)
index 0000000..ba0771b
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/machine/partition.h>
+#include <pupa/disk.h>
+#include <pupa/mm.h>
+#include <pupa/misc.h>
+
+/* Parse the partition representation in STR and return a partition.  */
+static pupa_partition_t
+pupa_partition_parse (const char *str)
+{
+  pupa_partition_t p;
+  char *s = (char *) str;
+  
+  p = (pupa_partition_t) pupa_malloc (sizeof (*p));
+  if (! p)
+    return 0;
+
+  /* Initialize some of the fields with invalid values.  */
+  p->bsd_part = p->dos_type = p->bsd_type = p->index = -1;
+
+  /* Get the DOS partition number.  */
+  p->dos_part = pupa_strtoul (s, &s, 0);
+  
+  if (pupa_errno)
+    {
+      /* Not found. Maybe only a BSD label is specified.  */
+      p->dos_part = -1;
+      pupa_errno = PUPA_ERR_NONE;
+    }
+  else if (*s == ',')
+    s++;
+
+  if (*s)
+    {
+      if (*s >= 'a' && *s <= 'h')
+       {
+         p->bsd_part = *s - 'a';
+         s++;
+       }
+
+      if (*s)
+       goto fail;
+    }
+
+  if (p->dos_part == -1 && p->bsd_part == -1)
+    goto fail;
+
+  return p;
+  
+ fail:
+  pupa_free (p);
+  pupa_error (PUPA_ERR_BAD_FILENAME, "invalid partition");
+  return 0;
+}
+
+pupa_err_t
+pupa_partition_iterate (pupa_disk_t disk,
+                       int (*hook) (const pupa_partition_t partition))
+{
+  struct pupa_partition p;
+  struct pupa_partition_mbr mbr;
+  struct pupa_partition_disk_label label;
+  struct pupa_disk raw;
+
+  /* Enforce raw disk access.  */
+  raw = *disk;
+  raw.partition = 0;
+  
+  p.offset = 0;
+  p.ext_offset = 0;
+  p.dos_part = -1;
+  
+  while (1)
+    {
+      int i;
+      struct pupa_partition_entry *e;
+      
+      /* Read the MBR.  */
+      if (pupa_disk_read (&raw, p.offset, 0, sizeof (mbr), (char *) &mbr))
+       goto finish;
+
+      /* Check if it is valid.  */
+      if (mbr.signature != pupa_cpu_to_le16 (PUPA_PARTITION_SIGNATURE))
+       return pupa_error (PUPA_ERR_BAD_PART_TABLE, "no signature");
+
+      /* Analyze DOS partitions.  */
+      for (p.index = 0; p.index < 4; p.index++)
+       {
+         e = mbr.entries + p.index;
+         
+         p.start = p.offset + pupa_le_to_cpu32 (e->start);
+         p.len = pupa_le_to_cpu32 (e->length);
+         p.bsd_part = -1;
+         p.dos_type = e->type;
+         p.bsd_type = -1;
+
+         /* If this partition is a normal one, call the hook.  */
+         if (! pupa_partition_is_empty (e->type)
+             && ! pupa_partition_is_extended (e->type))
+           {
+             p.dos_part++;
+             
+             if (hook (&p))
+               goto finish;
+
+             /* Check if this is a BSD partition.  */
+             if (pupa_partition_is_bsd (e->type))
+               {
+                 /* Check if the BSD label is within the DOS partition.  */
+                 if (p.len <= PUPA_PARTITION_BSD_LABEL_SECTOR)
+                   return pupa_error (PUPA_ERR_BAD_PART_TABLE,
+                                      "no space for disk label");
+
+                 /* Read the BSD label.  */
+                 if (pupa_disk_read (&raw,
+                                     (p.start
+                                      + PUPA_PARTITION_BSD_LABEL_SECTOR),
+                                     0,
+                                     sizeof (label),
+                                     (char *) &label))
+                   goto finish;
+
+                 /* Check if it is valid.  */
+                 if (label.magic
+                     != pupa_cpu_to_le32 (PUPA_PARTITION_BSD_LABEL_MAGIC))
+                   return pupa_error (PUPA_ERR_BAD_PART_TABLE,
+                                      "invalid disk label magic");
+
+                 for (p.bsd_part = 0;
+                      p.bsd_part < pupa_cpu_to_le16 (label.num_partitions);
+                      p.bsd_part++)
+                   {
+                     struct pupa_partition_bsd_entry *be
+                       = label.entries + p.bsd_part;
+
+                     p.start = pupa_le_to_cpu32 (be->offset);
+                     p.len = pupa_le_to_cpu32 (be->size);
+                     p.bsd_type = be->fs_type;
+                     
+                     if (be->fs_type != PUPA_PARTITION_BSD_TYPE_UNUSED)
+                       if (hook (&p))
+                         goto finish;
+                   }
+               }
+           }
+         else if (p.dos_part < 4)
+           /* If this partition is a logical one, shouldn't increase the
+              partition number.  */
+           p.dos_part++;
+       }
+
+      /* Find an extended partition.  */
+      for (i = 0; i < 4; i++)
+       {
+         e = mbr.entries + i;
+         
+         if (pupa_partition_is_extended (e->type))
+           {
+             p.offset = p.ext_offset + pupa_le_to_cpu32 (e->start);
+             if (! p.ext_offset)
+               p.ext_offset = p.offset;
+
+             break;
+           }
+       }
+
+      /* If no extended partition, the end.  */
+      if (i == 4)
+       break;
+    }
+
+ finish:
+  return pupa_errno;
+}
+
+pupa_partition_t
+pupa_partition_probe (pupa_disk_t disk, const char *str)
+{
+  pupa_partition_t p;
+  auto int find_func (const pupa_partition_t partition);
+
+  int find_func (const pupa_partition_t partition)
+    {
+      if ((p->dos_part == partition->dos_part || p->dos_part == -1)
+         && p->bsd_part == partition->bsd_part)
+       {
+         pupa_memcpy (p, partition, sizeof (*p));
+         return 1;
+       }
+      
+      return 0;
+    }
+  
+  p = pupa_partition_parse (str);
+  if (! p)
+    return 0;
+
+
+  if (pupa_partition_iterate (disk, find_func))
+    goto fail;
+
+  if (p->index < 0)
+    {
+      pupa_error (PUPA_ERR_BAD_DEVICE, "no such partition");
+      goto fail;
+    }
+
+  return p;
+
+ fail:
+  pupa_free (p);
+  return 0;
+}
+
+char *
+pupa_partition_get_name (const pupa_partition_t p)
+{
+  char *name;
+
+  name = pupa_malloc (13);
+  if (! name)
+    return 0;
+
+  if (p->bsd_part < 0)
+    pupa_sprintf (name, "%d", p->dos_part);
+  else
+    pupa_sprintf (name, "%d,%c", p->dos_part, p->bsd_part + 'a');
+
+  return name;
+}
diff --git a/fs/fat.c b/fs/fat.c
new file mode 100644 (file)
index 0000000..70abadc
--- /dev/null
+++ b/fs/fat.c
@@ -0,0 +1,756 @@
+/* fat.c - FAT filesystem */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2000,2001  Free Software Foundation, Inc.
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/fs.h>
+#include <pupa/disk.h>
+#include <pupa/file.h>
+#include <pupa/types.h>
+#include <pupa/misc.h>
+#include <pupa/mm.h>
+#include <pupa/err.h>
+#include <pupa/dl.h>
+
+#define PUPA_FAT_DIR_ENTRY_SIZE        32
+
+#define PUPA_FAT_ATTR_READ_ONLY        0x01
+#define PUPA_FAT_ATTR_HIDDEN   0x02
+#define PUPA_FAT_ATTR_SYSTEM   0x04
+#define PUPA_FAT_ATTR_VOLUME_ID        0x08
+#define PUPA_FAT_ATTR_DIRECTORY        0x10
+#define PUPA_FAT_ATTR_ARCHIVE  0x20
+
+#define PUPA_FAT_ATTR_LONG_NAME        (PUPA_FAT_ATTR_READ_ONLY \
+                                | PUPA_FAT_ATTR_HIDDEN \
+                                | PUPA_FAT_ATTR_SYSTEM \
+                                | PUPA_FAT_ATTR_VOLUME_ID)
+#define PUPA_FAT_ATTR_VALID    (PUPA_FAT_ATTR_READ_ONLY \
+                                | PUPA_FAT_ATTR_HIDDEN \
+                                | PUPA_FAT_ATTR_SYSTEM \
+                                | PUPA_FAT_ATTR_DIRECTORY \
+                                | PUPA_FAT_ATTR_ARCHIVE)
+
+struct pupa_fat_bpb
+{
+  pupa_uint8_t jmp_boot[3];
+  pupa_uint8_t oem_name[8];
+  pupa_uint16_t bytes_per_sector;
+  pupa_uint8_t sectors_per_cluster;
+  pupa_uint16_t num_reserved_sectors;
+  pupa_uint8_t num_fats;
+  pupa_uint16_t num_root_entries;
+  pupa_uint16_t num_total_sectors_16;
+  pupa_uint8_t media;
+  pupa_uint16_t sectors_per_fat_16;
+  pupa_uint16_t sectors_per_track;
+  pupa_uint16_t num_heads;
+  pupa_uint32_t num_hidden_sectors;
+  pupa_uint32_t num_total_sectors_32;
+  
+  /* The following fields are only used by FAT32.  */
+  pupa_uint32_t sectors_per_fat_32;
+  pupa_uint16_t extended_flags;
+  pupa_uint16_t fs_version;
+  pupa_uint32_t root_cluster;
+  pupa_uint16_t fs_info;
+  pupa_uint16_t backup_boot_sector;
+} __attribute__ ((packed));
+
+struct pupa_fat_dir_entry
+{
+  pupa_uint8_t name[11];
+  pupa_uint8_t attr;
+  pupa_uint8_t nt_reserved;
+  pupa_uint8_t c_time_tenth;
+  pupa_uint16_t c_time;
+  pupa_uint16_t c_date;
+  pupa_uint16_t a_date;
+  pupa_uint16_t first_cluster_high;
+  pupa_uint16_t w_time;
+  pupa_uint16_t w_date;
+  pupa_uint16_t first_cluster_low;
+  pupa_uint32_t file_size;
+} __attribute__ ((packed));
+
+struct pupa_fat_long_name_entry
+{
+  pupa_uint8_t id;
+  pupa_uint16_t name1[5];
+  pupa_uint8_t attr;
+  pupa_uint8_t reserved;
+  pupa_uint8_t checksum;
+  pupa_uint16_t name2[6];
+  pupa_uint16_t first_cluster;
+  pupa_uint16_t name3[2];
+} __attribute__ ((packed));
+
+struct pupa_fat_data
+{
+  int logical_sector_bits;
+  pupa_uint32_t num_sectors;
+  
+  pupa_uint16_t fat_sector;
+  pupa_uint32_t sectors_per_fat;
+  int fat_size;
+  
+  pupa_uint32_t root_cluster;
+  pupa_uint32_t root_sector;
+  pupa_uint32_t num_root_sectors;
+  
+  int cluster_bits;
+  pupa_uint32_t cluster_eof_mark;
+  pupa_uint32_t cluster_sector;
+  pupa_uint32_t num_clusters;
+
+  pupa_uint8_t attr;
+  pupa_ssize_t file_size;
+  pupa_uint32_t file_cluster;
+  pupa_uint32_t cur_cluster_num;
+  pupa_uint32_t cur_cluster;
+};
+
+static int
+log2 (unsigned x)
+{
+  int i;
+  
+  if (x == 0)
+    return -1;
+
+  for (i = 0; (x & 1) == 0; i++)
+    x >>= 1;
+
+  if (x != 1)
+    return -1;
+
+  return i;
+}
+
+static struct pupa_fat_data *
+pupa_fat_mount (pupa_disk_t disk)
+{
+  struct pupa_fat_bpb bpb;
+  struct pupa_fat_data *data = 0;
+  pupa_uint32_t first_fat, magic;
+
+  if (! disk)
+    goto fail;
+
+  data = (struct pupa_fat_data *) pupa_malloc (sizeof (*data));
+  if (! data)
+    goto fail;
+  
+  /* Read the BPB.  */
+  if (pupa_disk_read (disk, 0, 0, sizeof (bpb), (char *) &bpb))
+    goto fail;
+
+  /* Get the sizes of logical sectors and clusters.  */
+  data->logical_sector_bits = log2 (pupa_le_to_cpu16 (bpb.bytes_per_sector));
+  if (data->logical_sector_bits < PUPA_DISK_SECTOR_BITS)
+    goto fail;
+  data->logical_sector_bits -= PUPA_DISK_SECTOR_BITS;
+  
+  data->cluster_bits = log2 (bpb.sectors_per_cluster);
+  if (data->cluster_bits < 0)
+    goto fail;
+  data->cluster_bits += data->logical_sector_bits;
+
+  /* Get information about FATs.  */
+  data->fat_sector = (pupa_le_to_cpu16 (bpb.num_reserved_sectors)
+                     << data->logical_sector_bits);
+  if (data->fat_sector == 0)
+    goto fail;
+
+  data->sectors_per_fat = ((bpb.sectors_per_fat_16
+                           ? pupa_le_to_cpu16 (bpb.sectors_per_fat_16)
+                           : pupa_le_to_cpu32 (bpb.sectors_per_fat_32))
+                          << data->logical_sector_bits);
+  if (data->sectors_per_fat == 0)
+    goto fail;
+
+  /* Get the number of sectors in this volume.  */
+  data->num_sectors = ((bpb.num_total_sectors_16
+                       ? pupa_le_to_cpu16 (bpb.num_total_sectors_16)
+                       : pupa_le_to_cpu32 (bpb.num_total_sectors_32))
+                      << data->logical_sector_bits);
+  if (data->num_sectors == 0)
+    goto fail;
+
+  /* Get information about the root directory.  */
+  if (bpb.num_fats == 0)
+    goto fail;
+
+  data->root_sector = data->fat_sector + bpb.num_fats * data->sectors_per_fat;
+  data->num_root_sectors
+    = ((((pupa_uint32_t) pupa_le_to_cpu16 (bpb.num_root_entries)
+        * PUPA_FAT_DIR_ENTRY_SIZE
+        + pupa_le_to_cpu16 (bpb.bytes_per_sector) - 1)
+       >> (data->logical_sector_bits + PUPA_DISK_SECTOR_BITS))
+       << (data->logical_sector_bits));
+
+  data->cluster_sector = data->root_sector + data->num_root_sectors;
+  data->num_clusters = (((data->num_sectors - data->cluster_sector)
+                        >> (data->cluster_bits + data->logical_sector_bits))
+                       + 2);
+
+  if (data->num_clusters <= 2)
+    goto fail;
+
+  if (! bpb.sectors_per_fat_16)
+    {
+      /* FAT32.  */
+      pupa_uint16_t flags = pupa_le_to_cpu16 (bpb.extended_flags);
+      
+      data->root_cluster = pupa_le_to_cpu32 (bpb.root_cluster);
+      data->fat_size = 32;
+      data->cluster_eof_mark = 0x0ffffff8;
+      
+      if (flags & 0x80)
+       {
+         /* Get an active FAT.  */
+         unsigned active_fat = flags & 0xf;
+         
+         if (active_fat > bpb.num_fats)
+           goto fail;
+
+         data->fat_sector += active_fat * data->sectors_per_fat;
+       }
+
+      if (bpb.num_root_entries != 0 || bpb.fs_version != 0)
+       goto fail;
+    }
+  else
+    {
+      /* FAT12 or FAT16.  */
+      data->root_cluster = ~0UL;
+
+      if (data->num_clusters <= 4085 + 2)
+       {
+         /* FAT12.  */
+         data->fat_size = 12;
+         data->cluster_eof_mark = 0x0ff8;
+       }
+      else
+       {
+         /* FAT16.  */
+         data->fat_size = 16;
+         data->cluster_eof_mark = 0xfff8;
+       }
+    }
+
+  /* More sanity checks.  */
+  if (data->num_sectors <= data->fat_sector)
+    goto fail;
+
+  if (pupa_disk_read (disk,
+                     data->fat_sector,
+                     0,
+                     sizeof (first_fat),
+                     (char *) &first_fat))
+    goto fail;
+
+  first_fat = pupa_le_to_cpu32 (first_fat);
+
+  if (data->fat_size == 32)
+    {
+      first_fat &= 0x0fffffff;
+      magic = 0x0fffff00;
+    }
+  else if (data->fat_size == 16)
+    {
+      first_fat &= 0x0000ffff;
+      magic = 0xff00;
+    }
+  else
+    {
+      first_fat &= 0x00000fff;
+      magic = 0x0f00;
+    }
+  
+  if (first_fat != (magic | bpb.media))
+    goto fail;
+
+  /* Start from the root directory.  */
+  data->file_cluster = data->root_cluster;
+  data->cur_cluster_num = ~0UL;
+  data->attr = PUPA_FAT_ATTR_DIRECTORY;
+  return data;
+
+ fail:
+
+  pupa_free (data);
+  pupa_error (PUPA_ERR_BAD_FS, "not a fat filesystem");
+  return 0;
+}
+
+/* Convert UTF-16 (little endian) to UTF8.  */
+static pupa_uint8_t *
+pupa_fat_utf16_to_utf8 (pupa_uint8_t *dest, pupa_uint16_t *src,
+                       pupa_size_t size)
+{
+  pupa_uint32_t code_high = 0;
+
+  while (size--)
+    {
+      pupa_uint32_t code = pupa_le_to_cpu16 (*src++);
+
+      if (code_high)
+       {
+         if (code >= 0xDC00 && code <= 0xDFFF)
+           {
+             /* Surrogate pair.  */
+             code = ((code_high - 0xD800) << 12) + (code - 0xDC00) + 0x10000;
+             
+             *dest++ = (code >> 18) | 0xF0;
+             *dest++ = ((code >> 12) & 0x3F) | 0x80;
+             *dest++ = ((code >> 6) & 0x3F) | 0x80;
+             *dest++ = (code & 0x3F) | 0x80;
+           }
+         else
+           {
+             /* Error...  */
+             *dest++ = '?';
+           }
+
+         code_high = 0;
+       }
+      else
+       {
+         if (code <= 0x007F)
+           *dest++ = code;
+         else if (code <= 0x07FF)
+           {
+             *dest++ = (code >> 6) | 0xC0;
+             *dest++ = (code & 0x3F) | 0x80;
+           }
+         else if (code >= 0xD800 && code <= 0xDBFF)
+           {
+             code_high = code;
+             continue;
+           }
+         else if (code >= 0xDC00 && code <= 0xDFFF)
+           {
+             /* Error... */
+             *dest++ = '?';
+           }
+         else
+           {
+             *dest++ = (code >> 16) | 0xE0;
+             *dest++ = ((code >> 12) & 0x3F) | 0x80;
+             *dest++ = (code & 0x3F) | 0x80;
+           }
+       }
+    }
+
+  return dest;
+}
+
+static pupa_ssize_t
+pupa_fat_read_data (pupa_disk_t disk, struct pupa_fat_data *data,
+                   void (*read_hook) (unsigned long sector,
+                                      unsigned offset, unsigned length),
+                   pupa_ssize_t offset, pupa_ssize_t len, char *buf)
+{
+  pupa_ssize_t size;
+  pupa_uint32_t logical_cluster;
+  unsigned logical_cluster_bits;
+  pupa_ssize_t ret = 0;
+  unsigned long sector;
+  
+  /* This is a special case. FAT12 and FAT16 doesn't have the root directory
+     in clusters.  */
+  if (data->file_cluster == ~0UL)
+    {
+      size = (data->num_root_sectors << PUPA_DISK_SECTOR_BITS) - offset;
+      if (size > len)
+       size = len;
+
+      if (pupa_disk_read (disk, data->root_sector, offset, size, buf))
+       return -1;
+
+      return size;
+    }
+
+  /* Calculate the logical cluster number and offset.  */
+  logical_cluster_bits = (data->cluster_bits
+                         + data->logical_sector_bits
+                         + PUPA_DISK_SECTOR_BITS);
+  logical_cluster = offset >> logical_cluster_bits;
+  offset &= (1 << logical_cluster_bits) - 1;
+
+  if (logical_cluster < data->cur_cluster_num)
+    {
+      data->cur_cluster_num = 0;
+      data->cur_cluster = data->file_cluster;
+    }
+
+  while (len)
+    {
+      while (logical_cluster > data->cur_cluster_num)
+       {
+         /* Find next cluster.  */
+         pupa_uint32_t next_cluster;
+         unsigned long fat_offset;
+
+         switch (data->fat_size)
+           {
+           case 32:
+             fat_offset = data->cur_cluster << 2;
+             break;
+           case 16:
+             fat_offset = data->cur_cluster << 1;
+             break;
+           default:
+             /* case 12: */
+             fat_offset = data->cur_cluster + (data->cur_cluster >> 1);
+             break;
+           }
+
+         /* Read the FAT.  */
+         if (pupa_disk_read (disk, data->fat_sector, fat_offset,
+                             (data->fat_size + 7) >> 3,
+                             (char *) &next_cluster))
+           return -1;
+
+         next_cluster = pupa_le_to_cpu32 (next_cluster);
+         switch (data->fat_size)
+           {
+           case 16:
+             next_cluster &= 0xFFFF;
+             break;
+           case 12:
+             if (data->cur_cluster & 1)
+               next_cluster >>= 12;
+             
+             next_cluster &= 0x0FFF;
+             break;
+           }
+
+         /* Check the end.  */
+         if (next_cluster >= data->cluster_eof_mark)
+           return ret;
+
+         if (next_cluster < 2 || next_cluster >= data->num_clusters)
+           {
+             pupa_error (PUPA_ERR_BAD_FS, "invalid cluster");
+             return -1;
+           }
+
+         data->cur_cluster = next_cluster;
+         data->cur_cluster_num++;
+       }
+
+      /* Read the data here.  */
+      sector = (data->cluster_sector
+               + ((data->cur_cluster - 2)
+                  << (data->cluster_bits + data->logical_sector_bits)));
+      size = (1 << logical_cluster_bits) - offset;
+      if (size > len)
+       size = len;
+
+      disk->read_hook = read_hook;
+      pupa_disk_read (disk, sector, offset, size, buf);
+      disk->read_hook = 0;
+      if (pupa_errno)
+       return -1;
+
+      len -= size;
+      buf += size;
+      ret += size;
+      logical_cluster++;
+      offset = 0;
+    }
+
+  return ret;
+}
+
+/* Find the underlying directory or file in PATH and return the
+   next path. If there is no next path or an error occurs, return NULL.
+   If HOOK is specified, call it with each file name.  */
+static char *
+pupa_fat_find_dir (pupa_disk_t disk, struct pupa_fat_data *data,
+                  const char *path,
+                  int (*hook) (const char *filename, int dir))
+{
+  struct pupa_fat_dir_entry dir;
+  char *dirname, *dirp;
+  char *filename, *filep = 0;
+  pupa_uint16_t *unibuf;
+  int slot = -1, slots = -1;
+  int checksum = -1;
+  pupa_ssize_t offset = -sizeof(dir);
+  int call_hook;
+  
+  if (! (data->attr & PUPA_FAT_ATTR_DIRECTORY))
+    {
+      pupa_error (PUPA_ERR_BAD_FILE_TYPE, "not a directory");
+      return 0;
+    }
+  
+  /* Extract a directory name.  */
+  while (*path == '/')
+    path++;
+
+  dirp = pupa_strchr (path, '/');
+  if (dirp)
+    {
+      unsigned len = dirp - path;
+      
+      dirname = pupa_malloc (len + 1);
+      if (! dirname)
+       return 0;
+
+      pupa_memcpy (dirname, path, len);
+      dirname[len] = '\0';
+    }
+  else
+    /* This is actually a file.  */
+    dirname = pupa_strdup (path);
+
+  call_hook = (! dirp && hook);
+  
+  /* Allocate space enough to hold a long name.  */
+  filename = pupa_malloc (0x40 * 13 * 4 + 1);
+  unibuf = (pupa_uint16_t *) pupa_malloc (0x40 * 13 * 2);
+  if (! filename || ! unibuf)
+    {
+      pupa_free (filename);
+      pupa_free (unibuf);
+      pupa_free (dirname);
+      return 0;
+    }
+      
+  while (1)
+    {
+      unsigned i;
+
+      /* Adjust the offset.  */
+      offset += sizeof (dir);
+
+      /* Read a directory entry.  */
+      if ((pupa_fat_read_data (disk, data, 0,
+                              offset, sizeof (dir), (char *) &dir)
+          != sizeof (dir))
+         || dir.name[0] == 0)
+       {
+         if (pupa_errno == PUPA_ERR_NONE && ! call_hook)
+           pupa_error (PUPA_ERR_FILE_NOT_FOUND, "file not found");
+
+         break;
+       }
+
+      /* Handle long name entries.  */
+      if (dir.attr == PUPA_FAT_ATTR_LONG_NAME)
+       {
+         struct pupa_fat_long_name_entry *long_name
+           = (struct pupa_fat_long_name_entry *) &dir;
+         pupa_uint8_t id = long_name->id;
+         
+         if (id & 0x40)
+           {
+             id &= 0x3f;
+             slots = slot = id;
+             checksum = long_name->checksum;
+           }
+
+         if (id != slot || slot == 0 || checksum != long_name->checksum)
+           {
+             checksum = -1;
+             continue;
+           }
+
+         slot--;
+         pupa_memcpy (unibuf + slot * 13, long_name->name1, 5 * 2);
+         pupa_memcpy (unibuf + slot * 13 + 5, long_name->name2, 6 * 2);
+         pupa_memcpy (unibuf + slot * 13 + 11, long_name->name3, 2 * 2);
+         continue;
+       }
+
+      /* Check if this entry is valid.  */
+      if (dir.name[0] == 0xe5 || (dir.attr & ~PUPA_FAT_ATTR_VALID))
+       continue;
+
+      /* This is a workaround for Japanese.  */
+      if (dir.name[0] == 0x05)
+       dir.name[0] = 0xe5;
+      
+      if (checksum != -1 && slot == 0)
+       {
+         pupa_uint8_t sum;
+         
+         for (sum = 0, i = 0; i < sizeof (dir.name); i++)
+           sum = ((sum >> 1) | (sum << 7)) + dir.name[i];
+
+         if (sum == checksum)
+           {
+             *pupa_fat_utf16_to_utf8 (filename, unibuf, slots * 13) = '\0';
+             
+             if (*dirname == '\0' && call_hook)
+               {
+                 if (hook (filename, dir.attr & PUPA_FAT_ATTR_DIRECTORY))
+                   break;
+                 
+                 checksum = -1;
+                 continue;
+               }
+
+             if (pupa_strcmp (dirname, filename) == 0)
+               {
+                 if (call_hook)
+                   hook (filename, dir.attr & PUPA_FAT_ATTR_DIRECTORY);
+                 
+                 break;
+               }
+           }
+
+         checksum = -1;
+       }
+
+      /* Convert the 8.3 file name.  */
+      filep = filename;
+      
+      for (i = 0; i < 8 && dir.name[i] && ! pupa_isspace (dir.name[i]); i++)
+       *filep++ = pupa_tolower (dir.name[i]);
+      
+      *filep = '.';
+      
+      for (i = 8; i < 11 && dir.name[i] && ! pupa_isspace (dir.name[i]); i++)
+       *++filep = pupa_tolower (dir.name[i]);
+
+      if (*filep != '.')
+       filep++;
+      
+      *filep = '\0';
+
+      if (*dirname == '\0' && call_hook)
+       {
+         if (hook (filename, dir.attr & PUPA_FAT_ATTR_DIRECTORY))
+           break;
+       }
+      else if (pupa_strcmp (dirname, filename) == 0)
+       {
+         if (call_hook)
+           hook (filename, dir.attr & PUPA_FAT_ATTR_DIRECTORY);
+
+         break;
+       }
+    }
+
+  pupa_free (filename);
+  pupa_free (dirname);
+
+  data->attr = dir.attr;
+  data->file_size = pupa_le_to_cpu32 (dir.file_size);
+  data->file_cluster = ((pupa_le_to_cpu16 (dir.first_cluster_high) << 16)
+                       | pupa_le_to_cpu16 (dir.first_cluster_low));
+  data->cur_cluster_num = ~0UL;
+  
+  return dirp;
+}
+
+static pupa_err_t
+pupa_fat_dir (pupa_device_t device, const char *path,
+             int (*hook) (const char *filename, int dir))
+{
+  struct pupa_fat_data *data;
+  pupa_disk_t disk = device->disk;
+  char *p = (char *) path;
+  
+  data = pupa_fat_mount (disk);
+  if (! data)
+    return pupa_errno;
+
+  do
+    {
+      p = pupa_fat_find_dir (disk, data, p, hook);
+    }
+  while (p && pupa_errno == PUPA_ERR_NONE);
+
+  pupa_free (data);
+  return pupa_errno;
+}
+
+static pupa_err_t
+pupa_fat_open (pupa_file_t file, const char *name)
+{
+  struct pupa_fat_data *data;
+  char *p = (char *) name;
+  
+  data = pupa_fat_mount (file->device->disk);
+  if (! data)
+    return pupa_errno;
+
+  do
+    {
+      p = pupa_fat_find_dir (file->device->disk, data, p, 0);
+      if (pupa_errno != PUPA_ERR_NONE)
+       goto fail;
+    }
+  while (p);
+
+  if (data->attr & PUPA_FAT_ATTR_DIRECTORY)
+    {
+      pupa_error (PUPA_ERR_BAD_FILE_TYPE, "not a file");
+      goto fail;
+    }
+
+  file->data = data;
+  file->size = data->file_size;
+  
+  return PUPA_ERR_NONE;
+
+ fail:
+  pupa_free (data);
+  return pupa_errno;
+}
+
+static pupa_ssize_t
+pupa_fat_read (pupa_file_t file, char *buf, pupa_ssize_t len)
+{
+  return pupa_fat_read_data (file->device->disk, file->data, file->read_hook,
+                            file->offset, len, buf);
+}
+
+static pupa_err_t
+pupa_fat_close (pupa_file_t file)
+{
+  pupa_free (file->data);
+  return pupa_errno;
+}
+
+static struct pupa_fs pupa_fat_fs =
+  {
+    .name = "fat",
+    .dir = pupa_fat_dir,
+    .open = pupa_fat_open,
+    .read = pupa_fat_read,
+    .close = pupa_fat_close,
+    .next = 0
+  };
+
+PUPA_MOD_INIT
+{
+  pupa_fs_register (&pupa_fat_fs);
+}
+
+PUPA_MOD_FINI
+{
+  pupa_fs_unregister (&pupa_fat_fs);
+}
diff --git a/genkernsyms.sh b/genkernsyms.sh
new file mode 100644 (file)
index 0000000..0177ab3
--- /dev/null
@@ -0,0 +1,15 @@
+#! /bin/sh
+#
+# Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+#
+# This gensymlist.sh is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+cat $* | grep -v '^#' | sed -n '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/\1 kernel/;p;}'
+cat $* | grep -v '^#' | sed -n '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/\1 kernel/;p;}'
diff --git a/genmk.rb b/genmk.rb
new file mode 100644 (file)
index 0000000..7c621b9
--- /dev/null
+++ b/genmk.rb
@@ -0,0 +1,269 @@
+#! /usr/bin/ruby -w
+#
+# Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+#
+# This genmk.rb is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+module Enumerable
+  def collect_with_index
+    ret = []
+    self.each_with_index do |item, index|
+      ret.push(yield(item, index))
+    end
+    ret
+  end
+end
+
+class String
+  def to_var
+    self.gsub(/[^a-zA-Z0-9_@]/, '_')
+  end
+
+  def suffix(str)
+    self.sub(/\.[^\.]*$/, '') + '.' + str
+  end
+
+  def to_obj
+    self.sub(/\.[^\.]*$/, '').to_var + '.o'
+  end
+end
+
+class Image
+  def initialize(dir, name)
+    @dir = dir
+    @name = name
+  end
+  attr_reader :dir, :name
+
+  def rule(sources)
+    prefix = @name.to_var
+    exe = @name.suffix('exec')
+    objs = sources.collect do |src|
+      raise "unknown source file `#{src}'" if /\.[cS]$/ !~ src
+      prefix + '-' + src.to_obj
+    end
+    objs_str = objs.join(' ')
+    deps = objs.collect {|obj| obj.suffix('d')}
+    deps_str = deps.join(' ')
+    
+    "CLEANFILES += #{@name} #{exe} #{objs_str}
+MOSTLYCLEANFILES += #{deps_str}
+
+#{@name}: #{exe}
+       $(OBJCOPY) -O binary -R .note -R .comment $< $@
+
+#{exe}: #{objs_str}
+       $(CC) $(LDFLAGS) $(#{prefix}_LDFLAGS) -o $@ $^
+
+" + objs.collect_with_index do |obj, i|
+      src = sources[i]
+      fake_obj = File.basename(src).suffix('o')
+      dep = deps[i]
+      flag = if /\.c$/ =~ src then 'CFLAGS' else 'ASFLAGS' end
+      extra_flags = if /\.S$/ =~ src then '-DASM_FILE=1' else '' end
+      dir = File.dirname(src)
+      
+      "#{obj}: #{src}
+       $(CC) -I#{dir} -I$(srcdir)/#{dir} $(CPPFLAGS) #{extra_flags} $(#{flag}) $(#{prefix}_#{flag}) -c -o $@ $<
+
+#{dep}: #{src}
+       set -e; \
+         $(CC) -I#{dir} -I$(srcdir)/#{dir} $(CPPFLAGS) #{extra_flags} $(#{flag}) $(#{prefix}_#{flag}) -M $< \
+         | sed 's,#{Regexp.quote(fake_obj)}[ :]*,#{obj} $@ : ,g' > $@; \
+         [ -s $@ ] || rm -f $@
+
+-include #{dep}
+
+"
+    end.join('')
+  end
+end
+
+# Use PModule instead Module, to avoid name conflicting.
+class PModule
+  def initialize(dir, name)
+    @dir = dir
+    @name = name
+  end
+  attr_reader :dir, :name
+
+  def rule(sources)
+    prefix = @name.to_var
+    objs = sources.collect do |src|
+      raise "unknown source file `#{src}'" if /\.[cS]$/ !~ src
+      prefix + '-' + src.to_obj
+    end
+    objs_str = objs.join(' ')
+    deps = objs.collect {|obj| obj.suffix('d')}
+    deps_str = deps.join(' ')
+    pre_obj = 'pre-' + @name.suffix('o')
+    mod_src = 'mod-' + @name.suffix('c')
+    mod_obj = mod_src.suffix('o')
+    defsym = 'def-' + @name.suffix('lst')
+    undsym = 'und-' + @name.suffix('lst')
+    mod_name = File.basename(@name, '.mod')
+    
+    "CLEANFILES += #{@name} #{mod_obj} #{mod_src} #{pre_obj} #{objs_str} #{defsym} #{undsym}
+MOSTLYCLEANFILES += #{deps_str}
+DEFSYMFILES += #{defsym}
+UNDSYMFILES += #{undsym}
+
+#{@name}: #{pre_obj} #{mod_obj}
+       -rm -f $@
+       $(LD) -r -o $@ $^
+       $(STRIP) --strip-unneeded -K pupa_mod_init -K pupa_mod_fini -R .note -R .comment $@
+
+#{pre_obj}: #{objs_str}
+       -rm -f $@
+       $(LD) -r -o $@ $^
+
+#{mod_obj}: #{mod_src}
+       $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
+
+#{mod_src}: moddep.lst genmodsrc.sh
+       sh $(srcdir)/genmodsrc.sh '#{mod_name}' $< > $@ || (rm -f $@; exit 1)
+
+#{defsym}: #{pre_obj}
+       $(NM) -g --defined-only -P -p $< | sed 's/^\\([^ ]*\\).*/\\1 #{mod_name}/' > $@
+
+#{undsym}: #{pre_obj}
+       echo '#{mod_name}' > $@
+       $(NM) -u -P -p $< >> $@
+
+" + objs.collect_with_index do |obj, i|
+      src = sources[i]
+      fake_obj = File.basename(src).suffix('o')
+      dep = deps[i]
+      flag = if /\.c$/ =~ src then 'CFLAGS' else 'ASFLAGS' end
+      dir = File.dirname(src)
+
+      "#{obj}: #{src}
+       $(CC) -I#{dir} -I$(srcdir)/#{dir} $(CPPFLAGS) $(#{flag}) $(#{prefix}_#{flag}) -c -o $@ $<
+
+#{dep}: #{src}
+       set -e; \
+         $(CC) -I#{dir} -I$(srcdir)/#{dir} $(CPPFLAGS) $(#{flag}) $(#{prefix}_#{flag}) -M $< \
+         | sed 's,#{Regexp.quote(fake_obj)}[ :]*,#{obj} $@ : ,g' > $@; \
+         [ -s $@ ] || rm -f $@
+
+-include #{dep}
+
+"
+    end.join('')
+  end
+end
+
+class Utility
+  def initialize(dir, name)
+    @dir = dir
+    @name = name
+  end
+  attr_reader :dir, :name
+
+  def rule(sources)
+    prefix = @name.to_var
+    objs = sources.collect do |src|
+      raise "unknown source file `#{src}'" if /\.c$/ !~ src
+      prefix + '-' + src.to_obj
+    end
+    objs_str = objs.join(' ');
+    deps = objs.collect {|obj| obj.suffix('d')}
+    deps_str = deps.join(' ');
+
+    "CLEANFILES += #{@name} #{objs_str}
+MOSTLYCLEANFILES += #{deps_str}
+
+#{@name}: #{objs_str}
+       $(BUILD_CC) $(BUILD_LDFLAGS) $(#{prefix}_LDFLAGS) -o $@ $^
+
+" + objs.collect_with_index do |obj, i|
+      src = sources[i]
+      fake_obj = File.basename(src).suffix('o')
+      dep = deps[i]
+      dir = File.dirname(src)
+
+      "#{obj}: #{src}
+       $(BUILD_CC) -I#{dir} -I$(srcdir)/#{dir} $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(#{prefix}_CFLAGS) -c -o $@ $<
+
+#{dep}: #{src}
+       set -e; \
+         $(BUILD_CC) -I#{dir} -I$(srcdir)/#{dir} $(BUILD_CPPFLAGS) -DPUPA_UTIL=1 $(#{prefix}_CFLAGS) -M $< \
+         | sed 's,#{Regexp.quote(fake_obj)}[ :]*,#{obj} $@ : ,g' > $@; \
+         [ -s $@ ] || rm -f $@
+
+-include #{dep}
+
+"
+    end.join('')
+  end
+end
+
+images = []
+utils = []
+pmodules = []
+
+cont = false
+s = nil
+while l = gets
+  if cont
+    s += l
+  else
+    s = l
+  end
+
+  print l
+  cont = (/\\$/ =~ l)
+  unless cont
+    s.gsub!(/\\\n/, ' ')
+    
+    if /^([a-zA-Z0-9_]+)\s*=\s*(.*?)\s*$/ =~ s
+      var, args = $1, $2
+
+      if var =~ /^([a-zA-Z0-9_]+)_([A-Z]+)$/
+       prefix, type = $1, $2
+
+       case type
+       when 'IMAGES'
+         images += args.split(/\s+/).collect do |img|
+           Image.new(prefix, img)
+         end
+
+       when 'MODULES'
+         pmodules += args.split(/\s+/).collect do |pmod|
+           PModule.new(prefix, pmod)
+         end
+         
+       when 'UTILITIES'
+         utils += args.split(/\s+/).collect do |util|
+           Utility.new(prefix, util)
+         end
+
+       when 'SOURCES'
+         if img = images.detect() {|i| i.name.to_var == prefix}
+           print img.rule(args.split(/\s+/))
+         elsif pmod = pmodules.detect() {|m| m.name.to_var == prefix}
+           print pmod.rule(args.split(/\s+/))
+         elsif util = utils.detect() {|u| u.name.to_var == prefix}
+           print util.rule(args.split(/\s+/))
+         end
+       end
+      end
+      
+    end
+    
+  end
+  
+end
+
+puts "CLEANFILES += moddep.lst"
+puts "pkgdata_DATA += moddep.lst"
+puts "moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep"
+puts " cat $(DEFSYMFILES) /dev/null | ./genmoddep $(UNDSYMFILES) > $@ \\"
+puts "   || (rm -f $@; exit 1)"
diff --git a/genmodsrc.sh b/genmodsrc.sh
new file mode 100644 (file)
index 0000000..f02eb13
--- /dev/null
@@ -0,0 +1,48 @@
+#! /bin/sh
+#
+# Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+#
+# This genmodsrc.sh is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+set -e
+
+mod_name="$1"
+deps="$2"
+
+cat <<EOF
+/* This file is automatically generated by genmodsrc.sh. DO NOT EDIT! */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/dl.h>
+
+EOF
+
+echo "PUPA_MOD_NAME(${mod_name});"
+
+for mod in `grep "^${mod_name}:" ${deps} | sed 's/^[^:]*://'`; do
+  echo "PUPA_MOD_DEP(${mod});"
+done
diff --git a/gensymlist.sh b/gensymlist.sh
new file mode 100644 (file)
index 0000000..531ce1c
--- /dev/null
@@ -0,0 +1,65 @@
+#! /bin/sh
+#
+# Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+#
+# This gensymlist.sh is free software; the author
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+cat <<EOF
+/* This file is automatically generated by gensymlist.sh. DO NOT EDIT! */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+EOF
+
+for i in $*; do
+  echo "#include <$i>"
+done
+
+cat <<EOF
+
+void
+pupa_register_exported_symbols (void)
+{
+EOF
+
+cat <<EOF
+  struct symtab { const char *name; void *addr; };
+  struct symtab *p;
+  static struct symtab tab[] =
+    {
+EOF
+
+cat $* | grep -v '^#' | sed -n '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/      {"\1", \1},/;p;}'
+cat $* | grep -v '^#' | sed -n '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/      {"\1", \&\1},/;p;}'
+
+cat <<EOF
+      {0, 0}
+    };
+
+  for (p = tab; p->name; p++)
+    pupa_dl_register_symbol (p->name, p->addr, 0);
+}
+EOF
diff --git a/include/grub/boot.h b/include/grub/boot.h
new file mode 100644 (file)
index 0000000..bf897db
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_BOOT_HEADER
+#define PUPA_BOOT_HEADER       1
+
+#define PUPA_BOOT_VERSION_MAJOR        4
+#define PUPA_BOOT_VERSION_MINOR        0
+#define PUPA_BOOT_VERSION      ((PUPA_BOOT_VERSION_MINOR << 8) \
+                                       | PUPA_BOOT_VERSION_MAJOR)
+
+#endif /* ! PUPA_BOOT_HEADER */
diff --git a/include/grub/device.h b/include/grub/device.h
new file mode 100644 (file)
index 0000000..e8df53c
--- /dev/null
@@ -0,0 +1,44 @@
+/* device.h - device manager */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_DEVICE_HEADER
+#define PUPA_DEVICE_HEADER     1
+
+#include <pupa/symbol.h>
+#include <pupa/err.h>
+
+struct pupa_disk;
+struct pupa_net;
+struct pupa_fs;
+
+struct pupa_device
+{
+  struct pupa_disk *disk;
+  struct pupa_net *net;
+};
+typedef struct pupa_device *pupa_device_t;
+
+pupa_device_t EXPORT_FUNC(pupa_device_open) (const char *name);
+pupa_err_t EXPORT_FUNC(pupa_device_close) (pupa_device_t device);
+
+pupa_err_t EXPORT_FUNC(pupa_device_set_root) (const char *name);
+const char *EXPORT_FUNC(pupa_device_get_root) (void);
+
+#endif /* ! PUPA_DEVICE_HEADER */
diff --git a/include/grub/disk.h b/include/grub/disk.h
new file mode 100644 (file)
index 0000000..51bd5a6
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_DISK_HEADER
+#define PUPA_DISK_HEADER       1
+
+#include <pupa/symbol.h>
+#include <pupa/err.h>
+#include <pupa/types.h>
+
+struct pupa_disk;
+
+/* Disk device.  */
+struct pupa_disk_dev
+{
+  /* The device name.  */
+  const char *name;
+
+  /* Call HOOK with each device name, until HOOK returns non-zero.  */
+  int (*iterate) (int (*hook) (const char *name));
+
+  /* Open the device named NAME, and set up DISK.  */
+  pupa_err_t (*open) (const char *name, struct pupa_disk *disk);
+
+  /* Close the disk DISK.  */
+  void (*close) (struct pupa_disk *disk);
+
+  /* Read SIZE sectors from the sector SECTOR of the disk DISK into BUF.  */
+  pupa_err_t (*read) (struct pupa_disk *disk, unsigned long sector,
+                     unsigned long size, char *buf);
+
+  /* Write SIZE sectors from BUF into the sector SECTOR of the disk DISK.  */
+  pupa_err_t (*write) (struct pupa_disk *disk, unsigned long sector,
+                      unsigned long size, const char *buf);
+
+  /* The next disk device.  */
+  struct pupa_disk_dev *next;
+};
+typedef struct pupa_disk_dev *pupa_disk_dev_t;
+
+struct pupa_partition;
+
+/* Disk.  */
+struct pupa_disk
+{
+  /* The disk name.  */
+  const char *name;
+
+  /* The underlying disk device.  */
+  pupa_disk_dev_t dev;
+
+  /* The total number of sectors.  */
+  unsigned long total_sectors;
+
+  /* If partitions can be stored.  */
+  int has_partitions;
+
+  /* The id used by the disk cache manager.  */
+  unsigned long id;
+  
+  /* The partition information. This is machine-specific.  */
+  struct pupa_partition *partition;
+
+  /* Called when a sector was read.  */
+  void (*read_hook) (unsigned long sector, unsigned offset, unsigned length);
+
+  /* Device-specific data.  */
+  void *data;
+};
+typedef struct pupa_disk *pupa_disk_t;
+
+/* The sector size.  */
+#define PUPA_DISK_SECTOR_SIZE  0x200
+#define PUPA_DISK_SECTOR_BITS  9
+
+/* The maximum number of disk caches.  */
+#define PUPA_DISK_CACHE_NUM    1021
+
+/* The size of a disk cache in sector units.  */
+#define PUPA_DISK_CACHE_SIZE   8
+#define PUPA_DISK_CACHE_BITS   3
+
+/* This is called from the memory manager.  */
+void pupa_disk_cache_invalidate_all (void);
+
+void EXPORT_FUNC(pupa_disk_dev_register) (pupa_disk_dev_t dev);
+void EXPORT_FUNC(pupa_disk_dev_unregister) (pupa_disk_dev_t dev);
+void EXPORT_FUNC(pupa_disk_dev_iterate) (int (*hook) (const char *name));
+
+pupa_disk_t EXPORT_FUNC(pupa_disk_open) (const char *name);
+void EXPORT_FUNC(pupa_disk_close) (pupa_disk_t disk);
+pupa_err_t EXPORT_FUNC(pupa_disk_read) (pupa_disk_t disk,
+                                       unsigned long sector,
+                                       unsigned long offset,
+                                       unsigned long size,
+                                       char *buf);
+pupa_err_t EXPORT_FUNC(pupa_disk_write) (pupa_disk_t disk,
+                                        unsigned long sector,
+                                        unsigned long offset,
+                                        unsigned long size,
+                                        const char *buf);
+
+#endif /* ! PUPA_DISK_HEADER */
diff --git a/include/grub/dl.h b/include/grub/dl.h
new file mode 100644 (file)
index 0000000..2763497
--- /dev/null
@@ -0,0 +1,86 @@
+/* dl.h - types and prototypes for loadable module support */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_DL_H
+#define PUPA_DL_H      1
+
+#include <pupa/symbol.h>
+#include <pupa/err.h>
+#include <pupa/types.h>
+
+#define PUPA_MOD_INIT  \
+static void pupa_mod_init (void) __attribute__ ((unused)); \
+static void \
+pupa_mod_init (void)
+
+#define PUPA_MOD_FINI  \
+static void pupa_mod_fini (void) __attribute__ ((unused)); \
+static void \
+pupa_mod_fini (void)
+
+#define PUPA_MOD_NAME(name)    \
+__asm__ (".section .modname,\"S\"\n.string \"" #name "\"\n.previous")
+
+#define PUPA_MOD_DEP(name)     \
+__asm__ (".section .moddeps,\"S\"\n.string \"" #name "\"\n.previous")
+
+struct pupa_dl_segment
+{
+  struct pupa_dl_segment *next;
+  void *addr;
+  pupa_size_t size;
+  unsigned section;
+};
+typedef struct pupa_dl_segment *pupa_dl_segment_t;
+
+struct pupa_dl;
+
+struct pupa_dl_dep
+{
+  struct pupa_dl_dep *next;
+  struct pupa_dl *mod;
+};
+typedef struct pupa_dl_dep *pupa_dl_dep_t;
+
+struct pupa_dl
+{
+  char *name;
+  int ref_count;
+  pupa_dl_dep_t dep;
+  pupa_dl_segment_t segment;
+  void (*init) (void);
+  void (*fini) (void);
+};
+typedef struct pupa_dl *pupa_dl_t;
+
+pupa_dl_t EXPORT_FUNC(pupa_dl_load_file) (const char *filename);
+pupa_dl_t EXPORT_FUNC(pupa_dl_load) (const char *name);
+pupa_dl_t pupa_dl_load_core (void *addr, pupa_size_t size);
+void EXPORT_FUNC(pupa_dl_unload) (pupa_dl_t mod);
+pupa_dl_t EXPORT_FUNC(pupa_dl_get) (const char *name);
+pupa_err_t EXPORT_FUNC(pupa_dl_register_symbol) (const char *name, void *addr,
+                                           pupa_dl_t mod);
+void *EXPORT_FUNC(pupa_dl_resolve_symbol) (const char *name);
+void pupa_dl_init (const char *dir);
+
+int pupa_arch_dl_check_header (void *ehdr, pupa_size_t size);
+pupa_err_t pupa_arch_dl_relocate_symbols (pupa_dl_t mod, void *ehdr);
+
+#endif /* ! PUPA_DL_H */
diff --git a/include/grub/elf.h b/include/grub/elf.h
new file mode 100644 (file)
index 0000000..832e950
--- /dev/null
@@ -0,0 +1,2314 @@
+/* This file defines standard ELF types, structures, and macros.
+   Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+   This file was part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef PUPA_ELF_H
+#define        PUPA_ELF_H 1
+
+/* Standard ELF types.  */
+
+#include <pupa/types.h>
+
+/* Type for a 16-bit quantity.  */
+typedef pupa_uint16_t Elf32_Half;
+typedef pupa_uint16_t Elf64_Half;
+
+/* Types for signed and unsigned 32-bit quantities.  */
+typedef pupa_uint32_t Elf32_Word;
+typedef        pupa_int32_t  Elf32_Sword;
+typedef pupa_uint32_t Elf64_Word;
+typedef        pupa_int32_t  Elf64_Sword;
+
+/* Types for signed and unsigned 64-bit quantities.  */
+typedef pupa_uint64_t Elf32_Xword;
+typedef        pupa_int64_t  Elf32_Sxword;
+typedef pupa_uint64_t Elf64_Xword;
+typedef        pupa_int64_t  Elf64_Sxword;
+
+/* Type of addresses.  */
+typedef pupa_uint32_t Elf32_Addr;
+typedef pupa_uint64_t Elf64_Addr;
+
+/* Type of file offsets.  */
+typedef pupa_uint32_t Elf32_Off;
+typedef pupa_uint64_t Elf64_Off;
+
+/* Type for section indices, which are 16-bit quantities.  */
+typedef pupa_uint16_t Elf32_Section;
+typedef pupa_uint16_t Elf64_Section;
+
+/* Type for version symbol information.  */
+typedef Elf32_Half Elf32_Versym;
+typedef Elf64_Half Elf64_Versym;
+
+
+/* The ELF file header.  This appears at the start of every ELF file.  */
+
+#define EI_NIDENT (16)
+
+typedef struct
+{
+  unsigned char        e_ident[EI_NIDENT];     /* Magic number and other info */
+  Elf32_Half   e_type;                 /* Object file type */
+  Elf32_Half   e_machine;              /* Architecture */
+  Elf32_Word   e_version;              /* Object file version */
+  Elf32_Addr   e_entry;                /* Entry point virtual address */
+  Elf32_Off    e_phoff;                /* Program header table file offset */
+  Elf32_Off    e_shoff;                /* Section header table file offset */
+  Elf32_Word   e_flags;                /* Processor-specific flags */
+  Elf32_Half   e_ehsize;               /* ELF header size in bytes */
+  Elf32_Half   e_phentsize;            /* Program header table entry size */
+  Elf32_Half   e_phnum;                /* Program header table entry count */
+  Elf32_Half   e_shentsize;            /* Section header table entry size */
+  Elf32_Half   e_shnum;                /* Section header table entry count */
+  Elf32_Half   e_shstrndx;             /* Section header string table index */
+} Elf32_Ehdr;
+
+typedef struct
+{
+  unsigned char        e_ident[EI_NIDENT];     /* Magic number and other info */
+  Elf64_Half   e_type;                 /* Object file type */
+  Elf64_Half   e_machine;              /* Architecture */
+  Elf64_Word   e_version;              /* Object file version */
+  Elf64_Addr   e_entry;                /* Entry point virtual address */
+  Elf64_Off    e_phoff;                /* Program header table file offset */
+  Elf64_Off    e_shoff;                /* Section header table file offset */
+  Elf64_Word   e_flags;                /* Processor-specific flags */
+  Elf64_Half   e_ehsize;               /* ELF header size in bytes */
+  Elf64_Half   e_phentsize;            /* Program header table entry size */
+  Elf64_Half   e_phnum;                /* Program header table entry count */
+  Elf64_Half   e_shentsize;            /* Section header table entry size */
+  Elf64_Half   e_shnum;                /* Section header table entry count */
+  Elf64_Half   e_shstrndx;             /* Section header string table index */
+} Elf64_Ehdr;
+
+/* Fields in the e_ident array.  The EI_* macros are indices into the
+   array.  The macros under each EI_* macro are the values the byte
+   may have.  */
+
+#define EI_MAG0                0               /* File identification byte 0 index */
+#define ELFMAG0                0x7f            /* Magic number byte 0 */
+
+#define EI_MAG1                1               /* File identification byte 1 index */
+#define ELFMAG1                'E'             /* Magic number byte 1 */
+
+#define EI_MAG2                2               /* File identification byte 2 index */
+#define ELFMAG2                'L'             /* Magic number byte 2 */
+
+#define EI_MAG3                3               /* File identification byte 3 index */
+#define ELFMAG3                'F'             /* Magic number byte 3 */
+
+/* Conglomeration of the identification bytes, for easy testing as a word.  */
+#define        ELFMAG          "\177ELF"
+#define        SELFMAG         4
+
+#define EI_CLASS       4               /* File class byte index */
+#define ELFCLASSNONE   0               /* Invalid class */
+#define ELFCLASS32     1               /* 32-bit objects */
+#define ELFCLASS64     2               /* 64-bit objects */
+#define ELFCLASSNUM    3
+
+#define EI_DATA                5               /* Data encoding byte index */
+#define ELFDATANONE    0               /* Invalid data encoding */
+#define ELFDATA2LSB    1               /* 2's complement, little endian */
+#define ELFDATA2MSB    2               /* 2's complement, big endian */
+#define ELFDATANUM     3
+
+#define EI_VERSION     6               /* File version byte index */
+                                       /* Value must be EV_CURRENT */
+
+#define EI_OSABI       7               /* OS ABI identification */
+#define ELFOSABI_NONE          0       /* UNIX System V ABI */
+#define ELFOSABI_SYSV          0       /* Alias.  */
+#define ELFOSABI_HPUX          1       /* HP-UX */
+#define ELFOSABI_NETBSD                2       /* NetBSD.  */
+#define ELFOSABI_LINUX         3       /* Linux.  */
+#define ELFOSABI_SOLARIS       6       /* Sun Solaris.  */
+#define ELFOSABI_AIX           7       /* IBM AIX.  */
+#define ELFOSABI_IRIX          8       /* SGI Irix.  */
+#define ELFOSABI_FREEBSD       9       /* FreeBSD.  */
+#define ELFOSABI_TRU64         10      /* Compaq TRU64 UNIX.  */
+#define ELFOSABI_MODESTO       11      /* Novell Modesto.  */
+#define ELFOSABI_OPENBSD       12      /* OpenBSD.  */
+#define ELFOSABI_ARM           97      /* ARM */
+#define ELFOSABI_STANDALONE    255     /* Standalone (embedded) application */
+
+#define EI_ABIVERSION  8               /* ABI version */
+
+#define EI_PAD         9               /* Byte index of padding bytes */
+
+/* Legal values for e_type (object file type).  */
+
+#define ET_NONE                0               /* No file type */
+#define ET_REL         1               /* Relocatable file */
+#define ET_EXEC                2               /* Executable file */
+#define ET_DYN         3               /* Shared object file */
+#define ET_CORE                4               /* Core file */
+#define        ET_NUM          5               /* Number of defined types */
+#define ET_LOOS                0xfe00          /* OS-specific range start */
+#define ET_HIOS                0xfeff          /* OS-specific range end */
+#define ET_LOPROC      0xff00          /* Processor-specific range start */
+#define ET_HIPROC      0xffff          /* Processor-specific range end */
+
+/* Legal values for e_machine (architecture).  */
+
+#define EM_NONE                 0              /* No machine */
+#define EM_M32          1              /* AT&T WE 32100 */
+#define EM_SPARC        2              /* SUN SPARC */
+#define EM_386          3              /* Intel 80386 */
+#define EM_68K          4              /* Motorola m68k family */
+#define EM_88K          5              /* Motorola m88k family */
+#define EM_860          7              /* Intel 80860 */
+#define EM_MIPS                 8              /* MIPS R3000 big-endian */
+#define EM_S370                 9              /* IBM System/370 */
+#define EM_MIPS_RS3_LE 10              /* MIPS R3000 little-endian */
+
+#define EM_PARISC      15              /* HPPA */
+#define EM_VPP500      17              /* Fujitsu VPP500 */
+#define EM_SPARC32PLUS 18              /* Sun's "v8plus" */
+#define EM_960         19              /* Intel 80960 */
+#define EM_PPC         20              /* PowerPC */
+#define EM_PPC64       21              /* PowerPC 64-bit */
+#define EM_S390                22              /* IBM S390 */
+
+#define EM_V800                36              /* NEC V800 series */
+#define EM_FR20                37              /* Fujitsu FR20 */
+#define EM_RH32                38              /* TRW RH-32 */
+#define EM_RCE         39              /* Motorola RCE */
+#define EM_ARM         40              /* ARM */
+#define EM_FAKE_ALPHA  41              /* Digital Alpha */
+#define EM_SH          42              /* Hitachi SH */
+#define EM_SPARCV9     43              /* SPARC v9 64-bit */
+#define EM_TRICORE     44              /* Siemens Tricore */
+#define EM_ARC         45              /* Argonaut RISC Core */
+#define EM_H8_300      46              /* Hitachi H8/300 */
+#define EM_H8_300H     47              /* Hitachi H8/300H */
+#define EM_H8S         48              /* Hitachi H8S */
+#define EM_H8_500      49              /* Hitachi H8/500 */
+#define EM_IA_64       50              /* Intel Merced */
+#define EM_MIPS_X      51              /* Stanford MIPS-X */
+#define EM_COLDFIRE    52              /* Motorola Coldfire */
+#define EM_68HC12      53              /* Motorola M68HC12 */
+#define EM_MMA         54              /* Fujitsu MMA Multimedia Accelerator*/
+#define EM_PCP         55              /* Siemens PCP */
+#define EM_NCPU                56              /* Sony nCPU embeeded RISC */
+#define EM_NDR1                57              /* Denso NDR1 microprocessor */
+#define EM_STARCORE    58              /* Motorola Start*Core processor */
+#define EM_ME16                59              /* Toyota ME16 processor */
+#define EM_ST100       60              /* STMicroelectronic ST100 processor */
+#define EM_TINYJ       61              /* Advanced Logic Corp. Tinyj emb.fam*/
+#define EM_X86_64      62              /* AMD x86-64 architecture */
+#define EM_PDSP                63              /* Sony DSP Processor */
+
+#define EM_FX66                66              /* Siemens FX66 microcontroller */
+#define EM_ST9PLUS     67              /* STMicroelectronics ST9+ 8/16 mc */
+#define EM_ST7         68              /* STmicroelectronics ST7 8 bit mc */
+#define EM_68HC16      69              /* Motorola MC68HC16 microcontroller */
+#define EM_68HC11      70              /* Motorola MC68HC11 microcontroller */
+#define EM_68HC08      71              /* Motorola MC68HC08 microcontroller */
+#define EM_68HC05      72              /* Motorola MC68HC05 microcontroller */
+#define EM_SVX         73              /* Silicon Graphics SVx */
+#define EM_AT19                74              /* STMicroelectronics ST19 8 bit mc */
+#define EM_VAX         75              /* Digital VAX */
+#define EM_CRIS                76              /* Axis Communications 32-bit embedded processor */
+#define EM_JAVELIN     77              /* Infineon Technologies 32-bit embedded processor */
+#define EM_FIREPATH    78              /* Element 14 64-bit DSP Processor */
+#define EM_ZSP         79              /* LSI Logic 16-bit DSP Processor */
+#define EM_MMIX                80              /* Donald Knuth's educational 64-bit processor */
+#define EM_HUANY       81              /* Harvard University machine-independent object files */
+#define EM_PRISM       82              /* SiTera Prism */
+#define EM_AVR         83              /* Atmel AVR 8-bit microcontroller */
+#define EM_FR30                84              /* Fujitsu FR30 */
+#define EM_D10V                85              /* Mitsubishi D10V */
+#define EM_D30V                86              /* Mitsubishi D30V */
+#define EM_V850                87              /* NEC v850 */
+#define EM_M32R                88              /* Mitsubishi M32R */
+#define EM_MN10300     89              /* Matsushita MN10300 */
+#define EM_MN10200     90              /* Matsushita MN10200 */
+#define EM_PJ          91              /* picoJava */
+#define EM_OPENRISC    92              /* OpenRISC 32-bit embedded processor */
+#define EM_ARC_A5      93              /* ARC Cores Tangent-A5 */
+#define EM_XTENSA      94              /* Tensilica Xtensa Architecture */
+#define EM_NUM         95
+
+/* If it is necessary to assign new unofficial EM_* values, please
+   pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
+   chances of collision with official or non-GNU unofficial values.  */
+
+#define EM_ALPHA       0x9026
+
+/* Legal values for e_version (version).  */
+
+#define EV_NONE                0               /* Invalid ELF version */
+#define EV_CURRENT     1               /* Current version */
+#define EV_NUM         2
+
+/* Section header.  */
+
+typedef struct
+{
+  Elf32_Word   sh_name;                /* Section name (string tbl index) */
+  Elf32_Word   sh_type;                /* Section type */
+  Elf32_Word   sh_flags;               /* Section flags */
+  Elf32_Addr   sh_addr;                /* Section virtual addr at execution */
+  Elf32_Off    sh_offset;              /* Section file offset */
+  Elf32_Word   sh_size;                /* Section size in bytes */
+  Elf32_Word   sh_link;                /* Link to another section */
+  Elf32_Word   sh_info;                /* Additional section information */
+  Elf32_Word   sh_addralign;           /* Section alignment */
+  Elf32_Word   sh_entsize;             /* Entry size if section holds table */
+} Elf32_Shdr;
+
+typedef struct
+{
+  Elf64_Word   sh_name;                /* Section name (string tbl index) */
+  Elf64_Word   sh_type;                /* Section type */
+  Elf64_Xword  sh_flags;               /* Section flags */
+  Elf64_Addr   sh_addr;                /* Section virtual addr at execution */
+  Elf64_Off    sh_offset;              /* Section file offset */
+  Elf64_Xword  sh_size;                /* Section size in bytes */
+  Elf64_Word   sh_link;                /* Link to another section */
+  Elf64_Word   sh_info;                /* Additional section information */
+  Elf64_Xword  sh_addralign;           /* Section alignment */
+  Elf64_Xword  sh_entsize;             /* Entry size if section holds table */
+} Elf64_Shdr;
+
+/* Special section indices.  */
+
+#define SHN_UNDEF      0               /* Undefined section */
+#define SHN_LORESERVE  0xff00          /* Start of reserved indices */
+#define SHN_LOPROC     0xff00          /* Start of processor-specific */
+#define SHN_HIPROC     0xff1f          /* End of processor-specific */
+#define SHN_LOOS       0xff20          /* Start of OS-specific */
+#define SHN_HIOS       0xff3f          /* End of OS-specific */
+#define SHN_ABS                0xfff1          /* Associated symbol is absolute */
+#define SHN_COMMON     0xfff2          /* Associated symbol is common */
+#define SHN_XINDEX     0xffff          /* Index is in extra table.  */
+#define SHN_HIRESERVE  0xffff          /* End of reserved indices */
+
+/* Legal values for sh_type (section type).  */
+
+#define SHT_NULL         0             /* Section header table entry unused */
+#define SHT_PROGBITS     1             /* Program data */
+#define SHT_SYMTAB       2             /* Symbol table */
+#define SHT_STRTAB       3             /* String table */
+#define SHT_RELA         4             /* Relocation entries with addends */
+#define SHT_HASH         5             /* Symbol hash table */
+#define SHT_DYNAMIC      6             /* Dynamic linking information */
+#define SHT_NOTE         7             /* Notes */
+#define SHT_NOBITS       8             /* Program space with no data (bss) */
+#define SHT_REL                  9             /* Relocation entries, no addends */
+#define SHT_SHLIB        10            /* Reserved */
+#define SHT_DYNSYM       11            /* Dynamic linker symbol table */
+#define SHT_INIT_ARRAY   14            /* Array of constructors */
+#define SHT_FINI_ARRAY   15            /* Array of destructors */
+#define SHT_PREINIT_ARRAY 16           /* Array of pre-constructors */
+#define SHT_GROUP        17            /* Section group */
+#define SHT_SYMTAB_SHNDX  18           /* Extended section indeces */
+#define        SHT_NUM           19            /* Number of defined types.  */
+#define SHT_LOOS         0x60000000    /* Start OS-specific */
+#define SHT_GNU_LIBLIST          0x6ffffff7    /* Prelink library list */
+#define SHT_CHECKSUM     0x6ffffff8    /* Checksum for DSO content.  */
+#define SHT_LOSUNW       0x6ffffffa    /* Sun-specific low bound.  */
+#define SHT_SUNW_move    0x6ffffffa
+#define SHT_SUNW_COMDAT   0x6ffffffb
+#define SHT_SUNW_syminfo  0x6ffffffc
+#define SHT_GNU_verdef   0x6ffffffd    /* Version definition section.  */
+#define SHT_GNU_verneed          0x6ffffffe    /* Version needs section.  */
+#define SHT_GNU_versym   0x6fffffff    /* Version symbol table.  */
+#define SHT_HISUNW       0x6fffffff    /* Sun-specific high bound.  */
+#define SHT_HIOS         0x6fffffff    /* End OS-specific type */
+#define SHT_LOPROC       0x70000000    /* Start of processor-specific */
+#define SHT_HIPROC       0x7fffffff    /* End of processor-specific */
+#define SHT_LOUSER       0x80000000    /* Start of application-specific */
+#define SHT_HIUSER       0x8fffffff    /* End of application-specific */
+
+/* Legal values for sh_flags (section flags).  */
+
+#define SHF_WRITE           (1 << 0)   /* Writable */
+#define SHF_ALLOC           (1 << 1)   /* Occupies memory during execution */
+#define SHF_EXECINSTR       (1 << 2)   /* Executable */
+#define SHF_MERGE           (1 << 4)   /* Might be merged */
+#define SHF_STRINGS         (1 << 5)   /* Contains nul-terminated strings */
+#define SHF_INFO_LINK       (1 << 6)   /* `sh_info' contains SHT index */
+#define SHF_LINK_ORDER      (1 << 7)   /* Preserve order after combining */
+#define SHF_OS_NONCONFORMING (1 << 8)  /* Non-standard OS specific handling
+                                          required */
+#define SHF_GROUP           (1 << 9)   /* Section is member of a group.  */
+#define SHF_TLS                     (1 << 10)  /* Section hold thread-local data.  */
+#define SHF_MASKOS          0x0ff00000 /* OS-specific.  */
+#define SHF_MASKPROC        0xf0000000 /* Processor-specific */
+
+/* Section group handling.  */
+#define GRP_COMDAT     0x1             /* Mark group as COMDAT.  */
+
+/* Symbol table entry.  */
+
+typedef struct
+{
+  Elf32_Word   st_name;                /* Symbol name (string tbl index) */
+  Elf32_Addr   st_value;               /* Symbol value */
+  Elf32_Word   st_size;                /* Symbol size */
+  unsigned char        st_info;                /* Symbol type and binding */
+  unsigned char        st_other;               /* Symbol visibility */
+  Elf32_Section        st_shndx;               /* Section index */
+} Elf32_Sym;
+
+typedef struct
+{
+  Elf64_Word   st_name;                /* Symbol name (string tbl index) */
+  unsigned char        st_info;                /* Symbol type and binding */
+  unsigned char st_other;              /* Symbol visibility */
+  Elf64_Section        st_shndx;               /* Section index */
+  Elf64_Addr   st_value;               /* Symbol value */
+  Elf64_Xword  st_size;                /* Symbol size */
+} Elf64_Sym;
+
+/* The syminfo section if available contains additional information about
+   every dynamic symbol.  */
+
+typedef struct
+{
+  Elf32_Half si_boundto;               /* Direct bindings, symbol bound to */
+  Elf32_Half si_flags;                 /* Per symbol flags */
+} Elf32_Syminfo;
+
+typedef struct
+{
+  Elf64_Half si_boundto;               /* Direct bindings, symbol bound to */
+  Elf64_Half si_flags;                 /* Per symbol flags */
+} Elf64_Syminfo;
+
+/* Possible values for si_boundto.  */
+#define SYMINFO_BT_SELF                0xffff  /* Symbol bound to self */
+#define SYMINFO_BT_PARENT      0xfffe  /* Symbol bound to parent */
+#define SYMINFO_BT_LOWRESERVE  0xff00  /* Beginning of reserved entries */
+
+/* Possible bitmasks for si_flags.  */
+#define SYMINFO_FLG_DIRECT     0x0001  /* Direct bound symbol */
+#define SYMINFO_FLG_PASSTHRU   0x0002  /* Pass-thru symbol for translator */
+#define SYMINFO_FLG_COPY       0x0004  /* Symbol is a copy-reloc */
+#define SYMINFO_FLG_LAZYLOAD   0x0008  /* Symbol bound to object to be lazy
+                                          loaded */
+/* Syminfo version values.  */
+#define SYMINFO_NONE           0
+#define SYMINFO_CURRENT                1
+#define SYMINFO_NUM            2
+
+
+/* How to extract and insert information held in the st_info field.  */
+
+#define ELF32_ST_BIND(val)             (((unsigned char) (val)) >> 4)
+#define ELF32_ST_TYPE(val)             ((val) & 0xf)
+#define ELF32_ST_INFO(bind, type)      (((bind) << 4) + ((type) & 0xf))
+
+/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field.  */
+#define ELF64_ST_BIND(val)             ELF32_ST_BIND (val)
+#define ELF64_ST_TYPE(val)             ELF32_ST_TYPE (val)
+#define ELF64_ST_INFO(bind, type)      ELF32_ST_INFO ((bind), (type))
+
+/* Legal values for ST_BIND subfield of st_info (symbol binding).  */
+
+#define STB_LOCAL      0               /* Local symbol */
+#define STB_GLOBAL     1               /* Global symbol */
+#define STB_WEAK       2               /* Weak symbol */
+#define        STB_NUM         3               /* Number of defined types.  */
+#define STB_LOOS       10              /* Start of OS-specific */
+#define STB_HIOS       12              /* End of OS-specific */
+#define STB_LOPROC     13              /* Start of processor-specific */
+#define STB_HIPROC     15              /* End of processor-specific */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
+
+#define STT_NOTYPE     0               /* Symbol type is unspecified */
+#define STT_OBJECT     1               /* Symbol is a data object */
+#define STT_FUNC       2               /* Symbol is a code object */
+#define STT_SECTION    3               /* Symbol associated with a section */
+#define STT_FILE       4               /* Symbol's name is file name */
+#define STT_COMMON     5               /* Symbol is a common data object */
+#define STT_TLS                6               /* Symbol is thread-local data object*/
+#define        STT_NUM         7               /* Number of defined types.  */
+#define STT_LOOS       10              /* Start of OS-specific */
+#define STT_HIOS       12              /* End of OS-specific */
+#define STT_LOPROC     13              /* Start of processor-specific */
+#define STT_HIPROC     15              /* End of processor-specific */
+
+
+/* Symbol table indices are found in the hash buckets and chain table
+   of a symbol hash table section.  This special index value indicates
+   the end of a chain, meaning no further symbols are found in that bucket.  */
+
+#define STN_UNDEF      0               /* End of a chain.  */
+
+
+/* How to extract and insert information held in the st_other field.  */
+
+#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
+
+/* For ELF64 the definitions are the same.  */
+#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
+
+/* Symbol visibility specification encoded in the st_other field.  */
+#define STV_DEFAULT    0               /* Default symbol visibility rules */
+#define STV_INTERNAL   1               /* Processor specific hidden class */
+#define STV_HIDDEN     2               /* Sym unavailable in other modules */
+#define STV_PROTECTED  3               /* Not preemptible, not exported */
+
+
+/* Relocation table entry without addend (in section of type SHT_REL).  */
+
+typedef struct
+{
+  Elf32_Addr   r_offset;               /* Address */
+  Elf32_Word   r_info;                 /* Relocation type and symbol index */
+} Elf32_Rel;
+
+/* I have seen two different definitions of the Elf64_Rel and
+   Elf64_Rela structures, so we'll leave them out until Novell (or
+   whoever) gets their act together.  */
+/* The following, at least, is used on Sparc v9, MIPS, and Alpha.  */
+
+typedef struct
+{
+  Elf64_Addr   r_offset;               /* Address */
+  Elf64_Xword  r_info;                 /* Relocation type and symbol index */
+} Elf64_Rel;
+
+/* Relocation table entry with addend (in section of type SHT_RELA).  */
+
+typedef struct
+{
+  Elf32_Addr   r_offset;               /* Address */
+  Elf32_Word   r_info;                 /* Relocation type and symbol index */
+  Elf32_Sword  r_addend;               /* Addend */
+} Elf32_Rela;
+
+typedef struct
+{
+  Elf64_Addr   r_offset;               /* Address */
+  Elf64_Xword  r_info;                 /* Relocation type and symbol index */
+  Elf64_Sxword r_addend;               /* Addend */
+} Elf64_Rela;
+
+/* How to extract and insert information held in the r_info field.  */
+
+#define ELF32_R_SYM(val)               ((val) >> 8)
+#define ELF32_R_TYPE(val)              ((val) & 0xff)
+#define ELF32_R_INFO(sym, type)                (((sym) << 8) + ((type) & 0xff))
+
+#define ELF64_R_SYM(i)                 ((i) >> 32)
+#define ELF64_R_TYPE(i)                        ((i) & 0xffffffff)
+#define ELF64_R_INFO(sym,type)         ((((Elf64_Xword) (sym)) << 32) + (type))
+
+/* Program segment header.  */
+
+typedef struct
+{
+  Elf32_Word   p_type;                 /* Segment type */
+  Elf32_Off    p_offset;               /* Segment file offset */
+  Elf32_Addr   p_vaddr;                /* Segment virtual address */
+  Elf32_Addr   p_paddr;                /* Segment physical address */
+  Elf32_Word   p_filesz;               /* Segment size in file */
+  Elf32_Word   p_memsz;                /* Segment size in memory */
+  Elf32_Word   p_flags;                /* Segment flags */
+  Elf32_Word   p_align;                /* Segment alignment */
+} Elf32_Phdr;
+
+typedef struct
+{
+  Elf64_Word   p_type;                 /* Segment type */
+  Elf64_Word   p_flags;                /* Segment flags */
+  Elf64_Off    p_offset;               /* Segment file offset */
+  Elf64_Addr   p_vaddr;                /* Segment virtual address */
+  Elf64_Addr   p_paddr;                /* Segment physical address */
+  Elf64_Xword  p_filesz;               /* Segment size in file */
+  Elf64_Xword  p_memsz;                /* Segment size in memory */
+  Elf64_Xword  p_align;                /* Segment alignment */
+} Elf64_Phdr;
+
+/* Legal values for p_type (segment type).  */
+
+#define        PT_NULL         0               /* Program header table entry unused */
+#define PT_LOAD                1               /* Loadable program segment */
+#define PT_DYNAMIC     2               /* Dynamic linking information */
+#define PT_INTERP      3               /* Program interpreter */
+#define PT_NOTE                4               /* Auxiliary information */
+#define PT_SHLIB       5               /* Reserved */
+#define PT_PHDR                6               /* Entry for header table itself */
+#define PT_TLS         7               /* Thread-local storage segment */
+#define        PT_NUM          8               /* Number of defined types */
+#define PT_LOOS                0x60000000      /* Start of OS-specific */
+#define PT_GNU_EH_FRAME        0x6474e550      /* GCC .eh_frame_hdr segment */
+#define PT_LOSUNW      0x6ffffffa
+#define PT_SUNWBSS     0x6ffffffa      /* Sun Specific segment */
+#define PT_SUNWSTACK   0x6ffffffb      /* Stack segment */
+#define PT_HISUNW      0x6fffffff
+#define PT_HIOS                0x6fffffff      /* End of OS-specific */
+#define PT_LOPROC      0x70000000      /* Start of processor-specific */
+#define PT_HIPROC      0x7fffffff      /* End of processor-specific */
+
+/* Legal values for p_flags (segment flags).  */
+
+#define PF_X           (1 << 0)        /* Segment is executable */
+#define PF_W           (1 << 1)        /* Segment is writable */
+#define PF_R           (1 << 2)        /* Segment is readable */
+#define PF_MASKOS      0x0ff00000      /* OS-specific */
+#define PF_MASKPROC    0xf0000000      /* Processor-specific */
+
+/* Legal values for note segment descriptor types for core files. */
+
+#define NT_PRSTATUS    1               /* Contains copy of prstatus struct */
+#define NT_FPREGSET    2               /* Contains copy of fpregset struct */
+#define NT_PRPSINFO    3               /* Contains copy of prpsinfo struct */
+#define NT_PRXREG      4               /* Contains copy of prxregset struct */
+#define NT_PLATFORM    5               /* String from sysinfo(SI_PLATFORM) */
+#define NT_AUXV                6               /* Contains copy of auxv array */
+#define NT_GWINDOWS    7               /* Contains copy of gwindows struct */
+#define NT_ASRS                8               /* Contains copy of asrset struct */
+#define NT_PSTATUS     10              /* Contains copy of pstatus struct */
+#define NT_PSINFO      13              /* Contains copy of psinfo struct */
+#define NT_PRCRED      14              /* Contains copy of prcred struct */
+#define NT_UTSNAME     15              /* Contains copy of utsname struct */
+#define NT_LWPSTATUS   16              /* Contains copy of lwpstatus struct */
+#define NT_LWPSINFO    17              /* Contains copy of lwpinfo struct */
+#define NT_PRFPXREG    20              /* Contains copy of fprxregset struct*/
+
+/* Legal values for the note segment descriptor types for object files.  */
+
+#define NT_VERSION     1               /* Contains a version string.  */
+
+
+/* Dynamic section entry.  */
+
+typedef struct
+{
+  Elf32_Sword  d_tag;                  /* Dynamic entry type */
+  union
+    {
+      Elf32_Word d_val;                        /* Integer value */
+      Elf32_Addr d_ptr;                        /* Address value */
+    } d_un;
+} Elf32_Dyn;
+
+typedef struct
+{
+  Elf64_Sxword d_tag;                  /* Dynamic entry type */
+  union
+    {
+      Elf64_Xword d_val;               /* Integer value */
+      Elf64_Addr d_ptr;                        /* Address value */
+    } d_un;
+} Elf64_Dyn;
+
+/* Legal values for d_tag (dynamic entry type).  */
+
+#define DT_NULL                0               /* Marks end of dynamic section */
+#define DT_NEEDED      1               /* Name of needed library */
+#define DT_PLTRELSZ    2               /* Size in bytes of PLT relocs */
+#define DT_PLTGOT      3               /* Processor defined value */
+#define DT_HASH                4               /* Address of symbol hash table */
+#define DT_STRTAB      5               /* Address of string table */
+#define DT_SYMTAB      6               /* Address of symbol table */
+#define DT_RELA                7               /* Address of Rela relocs */
+#define DT_RELASZ      8               /* Total size of Rela relocs */
+#define DT_RELAENT     9               /* Size of one Rela reloc */
+#define DT_STRSZ       10              /* Size of string table */
+#define DT_SYMENT      11              /* Size of one symbol table entry */
+#define DT_INIT                12              /* Address of init function */
+#define DT_FINI                13              /* Address of termination function */
+#define DT_SONAME      14              /* Name of shared object */
+#define DT_RPATH       15              /* Library search path (deprecated) */
+#define DT_SYMBOLIC    16              /* Start symbol search here */
+#define DT_REL         17              /* Address of Rel relocs */
+#define DT_RELSZ       18              /* Total size of Rel relocs */
+#define DT_RELENT      19              /* Size of one Rel reloc */
+#define DT_PLTREL      20              /* Type of reloc in PLT */
+#define DT_DEBUG       21              /* For debugging; unspecified */
+#define DT_TEXTREL     22              /* Reloc might modify .text */
+#define DT_JMPREL      23              /* Address of PLT relocs */
+#define        DT_BIND_NOW     24              /* Process relocations of object */
+#define        DT_INIT_ARRAY   25              /* Array with addresses of init fct */
+#define        DT_FINI_ARRAY   26              /* Array with addresses of fini fct */
+#define        DT_INIT_ARRAYSZ 27              /* Size in bytes of DT_INIT_ARRAY */
+#define        DT_FINI_ARRAYSZ 28              /* Size in bytes of DT_FINI_ARRAY */
+#define DT_RUNPATH     29              /* Library search path */
+#define DT_FLAGS       30              /* Flags for the object being loaded */
+#define DT_ENCODING    32              /* Start of encoded range */
+#define DT_PREINIT_ARRAY 32            /* Array with addresses of preinit fct*/
+#define DT_PREINIT_ARRAYSZ 33          /* size in bytes of DT_PREINIT_ARRAY */
+#define        DT_NUM          34              /* Number used */
+#define DT_LOOS                0x6000000d      /* Start of OS-specific */
+#define DT_HIOS                0x6ffff000      /* End of OS-specific */
+#define DT_LOPROC      0x70000000      /* Start of processor-specific */
+#define DT_HIPROC      0x7fffffff      /* End of processor-specific */
+#define        DT_PROCNUM      DT_MIPS_NUM     /* Most used by any processor */
+
+/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
+   Dyn.d_un.d_val field of the Elf*_Dyn structure.  This follows Sun's
+   approach.  */
+#define DT_VALRNGLO    0x6ffffd00
+#define DT_GNU_PRELINKED 0x6ffffdf5    /* Prelinking timestamp */
+#define DT_GNU_CONFLICTSZ 0x6ffffdf6   /* Size of conflict section */
+#define DT_GNU_LIBLISTSZ 0x6ffffdf7    /* Size of library list */
+#define DT_CHECKSUM    0x6ffffdf8
+#define DT_PLTPADSZ    0x6ffffdf9
+#define DT_MOVEENT     0x6ffffdfa
+#define DT_MOVESZ      0x6ffffdfb
+#define DT_FEATURE_1   0x6ffffdfc      /* Feature selection (DTF_*).  */
+#define DT_POSFLAG_1   0x6ffffdfd      /* Flags for DT_* entries, effecting
+                                          the following DT_* entry.  */
+#define DT_SYMINSZ     0x6ffffdfe      /* Size of syminfo table (in bytes) */
+#define DT_SYMINENT    0x6ffffdff      /* Entry size of syminfo */
+#define DT_VALRNGHI    0x6ffffdff
+#define DT_VALTAGIDX(tag)      (DT_VALRNGHI - (tag))   /* Reverse order! */
+#define DT_VALNUM 12
+
+/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
+   Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
+
+   If any adjustment is made to the ELF object after it has been
+   built these entries will need to be adjusted.  */
+#define DT_ADDRRNGLO   0x6ffffe00
+#define DT_GNU_CONFLICT        0x6ffffef8      /* Start of conflict section */
+#define DT_GNU_LIBLIST 0x6ffffef9      /* Library list */
+#define DT_CONFIG      0x6ffffefa      /* Configuration information.  */
+#define DT_DEPAUDIT    0x6ffffefb      /* Dependency auditing.  */
+#define DT_AUDIT       0x6ffffefc      /* Object auditing.  */
+#define        DT_PLTPAD       0x6ffffefd      /* PLT padding.  */
+#define        DT_MOVETAB      0x6ffffefe      /* Move table.  */
+#define DT_SYMINFO     0x6ffffeff      /* Syminfo table.  */
+#define DT_ADDRRNGHI   0x6ffffeff
+#define DT_ADDRTAGIDX(tag)     (DT_ADDRRNGHI - (tag))  /* Reverse order! */
+#define DT_ADDRNUM 10
+
+/* The versioning entry types.  The next are defined as part of the
+   GNU extension.  */
+#define DT_VERSYM      0x6ffffff0
+
+#define DT_RELACOUNT   0x6ffffff9
+#define DT_RELCOUNT    0x6ffffffa
+
+/* These were chosen by Sun.  */
+#define DT_FLAGS_1     0x6ffffffb      /* State flags, see DF_1_* below.  */
+#define        DT_VERDEF       0x6ffffffc      /* Address of version definition
+                                          table */
+#define        DT_VERDEFNUM    0x6ffffffd      /* Number of version definitions */
+#define        DT_VERNEED      0x6ffffffe      /* Address of table with needed
+                                          versions */
+#define        DT_VERNEEDNUM   0x6fffffff      /* Number of needed versions */
+#define DT_VERSIONTAGIDX(tag)  (DT_VERNEEDNUM - (tag)) /* Reverse order! */
+#define DT_VERSIONTAGNUM 16
+
+/* Sun added these machine-independent extensions in the "processor-specific"
+   range.  Be compatible.  */
+#define DT_AUXILIARY    0x7ffffffd      /* Shared object to load before self */
+#define DT_FILTER       0x7fffffff      /* Shared object to get values from */
+#define DT_EXTRATAGIDX(tag)    ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
+#define DT_EXTRANUM    3
+
+/* Values of `d_un.d_val' in the DT_FLAGS entry.  */
+#define DF_ORIGIN      0x00000001      /* Object may use DF_ORIGIN */
+#define DF_SYMBOLIC    0x00000002      /* Symbol resolutions starts here */
+#define DF_TEXTREL     0x00000004      /* Object contains text relocations */
+#define DF_BIND_NOW    0x00000008      /* No lazy binding for this object */
+#define DF_STATIC_TLS  0x00000010      /* Module uses the static TLS model */
+
+/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1
+   entry in the dynamic section.  */
+#define DF_1_NOW       0x00000001      /* Set RTLD_NOW for this object.  */
+#define DF_1_GLOBAL    0x00000002      /* Set RTLD_GLOBAL for this object.  */
+#define DF_1_GROUP     0x00000004      /* Set RTLD_GROUP for this object.  */
+#define DF_1_NODELETE  0x00000008      /* Set RTLD_NODELETE for this object.*/
+#define DF_1_LOADFLTR  0x00000010      /* Trigger filtee loading at runtime.*/
+#define DF_1_INITFIRST 0x00000020      /* Set RTLD_INITFIRST for this object*/
+#define DF_1_NOOPEN    0x00000040      /* Set RTLD_NOOPEN for this object.  */
+#define DF_1_ORIGIN    0x00000080      /* $ORIGIN must be handled.  */
+#define DF_1_DIRECT    0x00000100      /* Direct binding enabled.  */
+#define DF_1_TRANS     0x00000200
+#define DF_1_INTERPOSE 0x00000400      /* Object is used to interpose.  */
+#define DF_1_NODEFLIB  0x00000800      /* Ignore default lib search path.  */
+#define DF_1_NODUMP    0x00001000      /* Object can't be dldump'ed.  */
+#define DF_1_CONFALT   0x00002000      /* Configuration alternative created.*/
+#define DF_1_ENDFILTEE 0x00004000      /* Filtee terminates filters search. */
+#define        DF_1_DISPRELDNE 0x00008000      /* Disp reloc applied at build time. */
+#define        DF_1_DISPRELPND 0x00010000      /* Disp reloc applied at run-time.  */
+
+/* Flags for the feature selection in DT_FEATURE_1.  */
+#define DTF_1_PARINIT  0x00000001
+#define DTF_1_CONFEXP  0x00000002
+
+/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry.  */
+#define DF_P1_LAZYLOAD 0x00000001      /* Lazyload following object.  */
+#define DF_P1_GROUPPERM        0x00000002      /* Symbols from next object are not
+                                          generally available.  */
+
+/* Version definition sections.  */
+
+typedef struct
+{
+  Elf32_Half   vd_version;             /* Version revision */
+  Elf32_Half   vd_flags;               /* Version information */
+  Elf32_Half   vd_ndx;                 /* Version Index */
+  Elf32_Half   vd_cnt;                 /* Number of associated aux entries */
+  Elf32_Word   vd_hash;                /* Version name hash value */
+  Elf32_Word   vd_aux;                 /* Offset in bytes to verdaux array */
+  Elf32_Word   vd_next;                /* Offset in bytes to next verdef
+                                          entry */
+} Elf32_Verdef;
+
+typedef struct
+{
+  Elf64_Half   vd_version;             /* Version revision */
+  Elf64_Half   vd_flags;               /* Version information */
+  Elf64_Half   vd_ndx;                 /* Version Index */
+  Elf64_Half   vd_cnt;                 /* Number of associated aux entries */
+  Elf64_Word   vd_hash;                /* Version name hash value */
+  Elf64_Word   vd_aux;                 /* Offset in bytes to verdaux array */
+  Elf64_Word   vd_next;                /* Offset in bytes to next verdef
+                                          entry */
+} Elf64_Verdef;
+
+
+/* Legal values for vd_version (version revision).  */
+#define VER_DEF_NONE   0               /* No version */
+#define VER_DEF_CURRENT        1               /* Current version */
+#define VER_DEF_NUM    2               /* Given version number */
+
+/* Legal values for vd_flags (version information flags).  */
+#define VER_FLG_BASE   0x1             /* Version definition of file itself */
+#define VER_FLG_WEAK   0x2             /* Weak version identifier */
+
+/* Versym symbol index values.  */
+#define        VER_NDX_LOCAL           0       /* Symbol is local.  */
+#define        VER_NDX_GLOBAL          1       /* Symbol is global.  */
+#define        VER_NDX_LORESERVE       0xff00  /* Beginning of reserved entries.  */
+#define        VER_NDX_ELIMINATE       0xff01  /* Symbol is to be eliminated.  */
+
+/* Auxialiary version information.  */
+
+typedef struct
+{
+  Elf32_Word   vda_name;               /* Version or dependency names */
+  Elf32_Word   vda_next;               /* Offset in bytes to next verdaux
+                                          entry */
+} Elf32_Verdaux;
+
+typedef struct
+{
+  Elf64_Word   vda_name;               /* Version or dependency names */
+  Elf64_Word   vda_next;               /* Offset in bytes to next verdaux
+                                          entry */
+} Elf64_Verdaux;
+
+
+/* Version dependency section.  */
+
+typedef struct
+{
+  Elf32_Half   vn_version;             /* Version of structure */
+  Elf32_Half   vn_cnt;                 /* Number of associated aux entries */
+  Elf32_Word   vn_file;                /* Offset of filename for this
+                                          dependency */
+  Elf32_Word   vn_aux;                 /* Offset in bytes to vernaux array */
+  Elf32_Word   vn_next;                /* Offset in bytes to next verneed
+                                          entry */
+} Elf32_Verneed;
+
+typedef struct
+{
+  Elf64_Half   vn_version;             /* Version of structure */
+  Elf64_Half   vn_cnt;                 /* Number of associated aux entries */
+  Elf64_Word   vn_file;                /* Offset of filename for this
+                                          dependency */
+  Elf64_Word   vn_aux;                 /* Offset in bytes to vernaux array */
+  Elf64_Word   vn_next;                /* Offset in bytes to next verneed
+                                          entry */
+} Elf64_Verneed;
+
+
+/* Legal values for vn_version (version revision).  */
+#define VER_NEED_NONE   0              /* No version */
+#define VER_NEED_CURRENT 1             /* Current version */
+#define VER_NEED_NUM    2              /* Given version number */
+
+/* Auxiliary needed version information.  */
+
+typedef struct
+{
+  Elf32_Word   vna_hash;               /* Hash value of dependency name */
+  Elf32_Half   vna_flags;              /* Dependency specific information */
+  Elf32_Half   vna_other;              /* Unused */
+  Elf32_Word   vna_name;               /* Dependency name string offset */
+  Elf32_Word   vna_next;               /* Offset in bytes to next vernaux
+                                          entry */
+} Elf32_Vernaux;
+
+typedef struct
+{
+  Elf64_Word   vna_hash;               /* Hash value of dependency name */
+  Elf64_Half   vna_flags;              /* Dependency specific information */
+  Elf64_Half   vna_other;              /* Unused */
+  Elf64_Word   vna_name;               /* Dependency name string offset */
+  Elf64_Word   vna_next;               /* Offset in bytes to next vernaux
+                                          entry */
+} Elf64_Vernaux;
+
+
+/* Legal values for vna_flags.  */
+#define VER_FLG_WEAK   0x2             /* Weak version identifier */
+
+
+/* Auxiliary vector.  */
+
+/* This vector is normally only used by the program interpreter.  The
+   usual definition in an ABI supplement uses the name auxv_t.  The
+   vector is not usually defined in a standard <elf.h> file, but it
+   can't hurt.  We rename it to avoid conflicts.  The sizes of these
+   types are an arrangement between the exec server and the program
+   interpreter, so we don't fully specify them here.  */
+
+typedef struct
+{
+  int a_type;                  /* Entry type */
+  union
+    {
+      long int a_val;          /* Integer value */
+      void *a_ptr;             /* Pointer value */
+      void (*a_fcn) (void);    /* Function pointer value */
+    } a_un;
+} Elf32_auxv_t;
+
+typedef struct
+{
+  long int a_type;             /* Entry type */
+  union
+    {
+      long int a_val;          /* Integer value */
+      void *a_ptr;             /* Pointer value */
+      void (*a_fcn) (void);    /* Function pointer value */
+    } a_un;
+} Elf64_auxv_t;
+
+/* Legal values for a_type (entry type).  */
+
+#define AT_NULL                0               /* End of vector */
+#define AT_IGNORE      1               /* Entry should be ignored */
+#define AT_EXECFD      2               /* File descriptor of program */
+#define AT_PHDR                3               /* Program headers for program */
+#define AT_PHENT       4               /* Size of program header entry */
+#define AT_PHNUM       5               /* Number of program headers */
+#define AT_PAGESZ      6               /* System page size */
+#define AT_BASE                7               /* Base address of interpreter */
+#define AT_FLAGS       8               /* Flags */
+#define AT_ENTRY       9               /* Entry point of program */
+#define AT_NOTELF      10              /* Program is not ELF */
+#define AT_UID         11              /* Real uid */
+#define AT_EUID                12              /* Effective uid */
+#define AT_GID         13              /* Real gid */
+#define AT_EGID                14              /* Effective gid */
+#define AT_CLKTCK      17              /* Frequency of times() */
+
+/* Some more special a_type values describing the hardware.  */
+#define AT_PLATFORM    15              /* String identifying platform.  */
+#define AT_HWCAP       16              /* Machine dependent hints about
+                                          processor capabilities.  */
+
+/* This entry gives some information about the FPU initialization
+   performed by the kernel.  */
+#define AT_FPUCW       18              /* Used FPU control word.  */
+
+/* Cache block sizes.  */
+#define AT_DCACHEBSIZE 19              /* Data cache block size.  */
+#define AT_ICACHEBSIZE 20              /* Instruction cache block size.  */
+#define AT_UCACHEBSIZE 21              /* Unified cache block size.  */
+
+/* A special ignored value for PPC, used by the kernel to control the
+   interpretation of the AUXV. Must be > 16.  */
+#define AT_IGNOREPPC   22              /* Entry should be ignored */
+
+
+/* Note section contents.  Each entry in the note section begins with
+   a header of a fixed form.  */
+
+typedef struct
+{
+  Elf32_Word n_namesz;                 /* Length of the note's name.  */
+  Elf32_Word n_descsz;                 /* Length of the note's descriptor.  */
+  Elf32_Word n_type;                   /* Type of the note.  */
+} Elf32_Nhdr;
+
+typedef struct
+{
+  Elf64_Word n_namesz;                 /* Length of the note's name.  */
+  Elf64_Word n_descsz;                 /* Length of the note's descriptor.  */
+  Elf64_Word n_type;                   /* Type of the note.  */
+} Elf64_Nhdr;
+
+/* Known names of notes.  */
+
+/* Solaris entries in the note section have this name.  */
+#define ELF_NOTE_SOLARIS       "SUNW Solaris"
+
+/* Note entries for GNU systems have this name.  */
+#define ELF_NOTE_GNU           "GNU"
+
+
+/* Defined types of notes for Solaris.  */
+
+/* Value of descriptor (one word) is desired pagesize for the binary.  */
+#define ELF_NOTE_PAGESIZE_HINT 1
+
+
+/* Defined note types for GNU systems.  */
+
+/* ABI information.  The descriptor consists of words:
+   word 0: OS descriptor
+   word 1: major version of the ABI
+   word 2: minor version of the ABI
+   word 3: subminor version of the ABI
+*/
+#define ELF_NOTE_ABI           1
+
+/* Known OSes.  These value can appear in word 0 of an ELF_NOTE_ABI
+   note section entry.  */
+#define ELF_NOTE_OS_LINUX      0
+#define ELF_NOTE_OS_GNU                1
+#define ELF_NOTE_OS_SOLARIS2   2
+
+
+/* Move records.  */
+typedef struct
+{
+  Elf32_Xword m_value;         /* Symbol value.  */
+  Elf32_Word m_info;           /* Size and index.  */
+  Elf32_Word m_poffset;                /* Symbol offset.  */
+  Elf32_Half m_repeat;         /* Repeat count.  */
+  Elf32_Half m_stride;         /* Stride info.  */
+} Elf32_Move;
+
+typedef struct
+{
+  Elf64_Xword m_value;         /* Symbol value.  */
+  Elf64_Xword m_info;          /* Size and index.  */
+  Elf64_Xword m_poffset;       /* Symbol offset.  */
+  Elf64_Half m_repeat;         /* Repeat count.  */
+  Elf64_Half m_stride;         /* Stride info.  */
+} Elf64_Move;
+
+/* Macro to construct move records.  */
+#define ELF32_M_SYM(info)      ((info) >> 8)
+#define ELF32_M_SIZE(info)     ((unsigned char) (info))
+#define ELF32_M_INFO(sym, size)        (((sym) << 8) + (unsigned char) (size))
+
+#define ELF64_M_SYM(info)      ELF32_M_SYM (info)
+#define ELF64_M_SIZE(info)     ELF32_M_SIZE (info)
+#define ELF64_M_INFO(sym, size)        ELF32_M_INFO (sym, size)
+
+
+/* Motorola 68k specific definitions.  */
+
+/* Values for Elf32_Ehdr.e_flags.  */
+#define EF_CPU32       0x00810000
+
+/* m68k relocs.  */
+
+#define R_68K_NONE     0               /* No reloc */
+#define R_68K_32       1               /* Direct 32 bit  */
+#define R_68K_16       2               /* Direct 16 bit  */
+#define R_68K_8                3               /* Direct 8 bit  */
+#define R_68K_PC32     4               /* PC relative 32 bit */
+#define R_68K_PC16     5               /* PC relative 16 bit */
+#define R_68K_PC8      6               /* PC relative 8 bit */
+#define R_68K_GOT32    7               /* 32 bit PC relative GOT entry */
+#define R_68K_GOT16    8               /* 16 bit PC relative GOT entry */
+#define R_68K_GOT8     9               /* 8 bit PC relative GOT entry */
+#define R_68K_GOT32O   10              /* 32 bit GOT offset */
+#define R_68K_GOT16O   11              /* 16 bit GOT offset */
+#define R_68K_GOT8O    12              /* 8 bit GOT offset */
+#define R_68K_PLT32    13              /* 32 bit PC relative PLT address */
+#define R_68K_PLT16    14              /* 16 bit PC relative PLT address */
+#define R_68K_PLT8     15              /* 8 bit PC relative PLT address */
+#define R_68K_PLT32O   16              /* 32 bit PLT offset */
+#define R_68K_PLT16O   17              /* 16 bit PLT offset */
+#define R_68K_PLT8O    18              /* 8 bit PLT offset */
+#define R_68K_COPY     19              /* Copy symbol at runtime */
+#define R_68K_GLOB_DAT 20              /* Create GOT entry */
+#define R_68K_JMP_SLOT 21              /* Create PLT entry */
+#define R_68K_RELATIVE 22              /* Adjust by program base */
+/* Keep this the last entry.  */
+#define R_68K_NUM      23
+
+/* Intel 80386 specific definitions.  */
+
+/* i386 relocs.  */
+
+#define R_386_NONE        0            /* No reloc */
+#define R_386_32          1            /* Direct 32 bit  */
+#define R_386_PC32        2            /* PC relative 32 bit */
+#define R_386_GOT32       3            /* 32 bit GOT entry */
+#define R_386_PLT32       4            /* 32 bit PLT address */
+#define R_386_COPY        5            /* Copy symbol at runtime */
+#define R_386_GLOB_DAT    6            /* Create GOT entry */
+#define R_386_JMP_SLOT    7            /* Create PLT entry */
+#define R_386_RELATIVE    8            /* Adjust by program base */
+#define R_386_GOTOFF      9            /* 32 bit offset to GOT */
+#define R_386_GOTPC       10           /* 32 bit PC relative offset to GOT */
+#define R_386_32PLT       11
+#define R_386_TLS_TPOFF           14           /* Offset in static TLS block */
+#define R_386_TLS_IE      15           /* Address of GOT entry for static TLS
+                                          block offset */
+#define R_386_TLS_GOTIE           16           /* GOT entry for static TLS block
+                                          offset */
+#define R_386_TLS_LE      17           /* Offset relative to static TLS
+                                          block */
+#define R_386_TLS_GD      18           /* Direct 32 bit for GNU version of
+                                          general dynamic thread local data */
+#define R_386_TLS_LDM     19           /* Direct 32 bit for GNU version of
+                                          local dynamic thread local data
+                                          in LE code */
+#define R_386_16          20
+#define R_386_PC16        21
+#define R_386_8                   22
+#define R_386_PC8         23
+#define R_386_TLS_GD_32           24           /* Direct 32 bit for general dynamic
+                                          thread local data */
+#define R_386_TLS_GD_PUSH  25          /* Tag for pushl in GD TLS code */
+#define R_386_TLS_GD_CALL  26          /* Relocation for call to
+                                          __tls_get_addr() */
+#define R_386_TLS_GD_POP   27          /* Tag for popl in GD TLS code */
+#define R_386_TLS_LDM_32   28          /* Direct 32 bit for local dynamic
+                                          thread local data in LE code */
+#define R_386_TLS_LDM_PUSH 29          /* Tag for pushl in LDM TLS code */
+#define R_386_TLS_LDM_CALL 30          /* Relocation for call to
+                                          __tls_get_addr() in LDM code */
+#define R_386_TLS_LDM_POP  31          /* Tag for popl in LDM TLS code */
+#define R_386_TLS_LDO_32   32          /* Offset relative to TLS block */
+#define R_386_TLS_IE_32           33           /* GOT entry for negated static TLS
+                                          block offset */
+#define R_386_TLS_LE_32           34           /* Negated offset relative to static
+                                          TLS block */
+#define R_386_TLS_DTPMOD32 35          /* ID of module containing symbol */
+#define R_386_TLS_DTPOFF32 36          /* Offset in TLS block */
+#define R_386_TLS_TPOFF32  37          /* Negated offset in static TLS block */
+/* Keep this the last entry.  */
+#define R_386_NUM         38
+
+/* SUN SPARC specific definitions.  */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
+
+#define STT_REGISTER   13              /* Global register reserved to app. */
+
+/* Values for Elf64_Ehdr.e_flags.  */
+
+#define EF_SPARCV9_MM          3
+#define EF_SPARCV9_TSO         0
+#define EF_SPARCV9_PSO         1
+#define EF_SPARCV9_RMO         2
+#define EF_SPARC_LEDATA                0x800000 /* little endian data */
+#define EF_SPARC_EXT_MASK      0xFFFF00
+#define EF_SPARC_32PLUS                0x000100 /* generic V8+ features */
+#define EF_SPARC_SUN_US1       0x000200 /* Sun UltraSPARC1 extensions */
+#define EF_SPARC_HAL_R1                0x000400 /* HAL R1 extensions */
+#define EF_SPARC_SUN_US3       0x000800 /* Sun UltraSPARCIII extensions */
+
+/* SPARC relocs.  */
+
+#define R_SPARC_NONE           0       /* No reloc */
+#define R_SPARC_8              1       /* Direct 8 bit */
+#define R_SPARC_16             2       /* Direct 16 bit */
+#define R_SPARC_32             3       /* Direct 32 bit */
+#define R_SPARC_DISP8          4       /* PC relative 8 bit */
+#define R_SPARC_DISP16         5       /* PC relative 16 bit */
+#define R_SPARC_DISP32         6       /* PC relative 32 bit */
+#define R_SPARC_WDISP30                7       /* PC relative 30 bit shifted */
+#define R_SPARC_WDISP22                8       /* PC relative 22 bit shifted */
+#define R_SPARC_HI22           9       /* High 22 bit */
+#define R_SPARC_22             10      /* Direct 22 bit */
+#define R_SPARC_13             11      /* Direct 13 bit */
+#define R_SPARC_LO10           12      /* Truncated 10 bit */
+#define R_SPARC_GOT10          13      /* Truncated 10 bit GOT entry */
+#define R_SPARC_GOT13          14      /* 13 bit GOT entry */
+#define R_SPARC_GOT22          15      /* 22 bit GOT entry shifted */
+#define R_SPARC_PC10           16      /* PC relative 10 bit truncated */
+#define R_SPARC_PC22           17      /* PC relative 22 bit shifted */
+#define R_SPARC_WPLT30         18      /* 30 bit PC relative PLT address */
+#define R_SPARC_COPY           19      /* Copy symbol at runtime */
+#define R_SPARC_GLOB_DAT       20      /* Create GOT entry */
+#define R_SPARC_JMP_SLOT       21      /* Create PLT entry */
+#define R_SPARC_RELATIVE       22      /* Adjust by program base */
+#define R_SPARC_UA32           23      /* Direct 32 bit unaligned */
+
+/* Additional Sparc64 relocs.  */
+
+#define R_SPARC_PLT32          24      /* Direct 32 bit ref to PLT entry */
+#define R_SPARC_HIPLT22                25      /* High 22 bit PLT entry */
+#define R_SPARC_LOPLT10                26      /* Truncated 10 bit PLT entry */
+#define R_SPARC_PCPLT32                27      /* PC rel 32 bit ref to PLT entry */
+#define R_SPARC_PCPLT22                28      /* PC rel high 22 bit PLT entry */
+#define R_SPARC_PCPLT10                29      /* PC rel trunc 10 bit PLT entry */
+#define R_SPARC_10             30      /* Direct 10 bit */
+#define R_SPARC_11             31      /* Direct 11 bit */
+#define R_SPARC_64             32      /* Direct 64 bit */
+#define R_SPARC_OLO10          33      /* 10bit with secondary 13bit addend */
+#define R_SPARC_HH22           34      /* Top 22 bits of direct 64 bit */
+#define R_SPARC_HM10           35      /* High middle 10 bits of ... */
+#define R_SPARC_LM22           36      /* Low middle 22 bits of ... */
+#define R_SPARC_PC_HH22                37      /* Top 22 bits of pc rel 64 bit */
+#define R_SPARC_PC_HM10                38      /* High middle 10 bit of ... */
+#define R_SPARC_PC_LM22                39      /* Low miggle 22 bits of ... */
+#define R_SPARC_WDISP16                40      /* PC relative 16 bit shifted */
+#define R_SPARC_WDISP19                41      /* PC relative 19 bit shifted */
+#define R_SPARC_7              43      /* Direct 7 bit */
+#define R_SPARC_5              44      /* Direct 5 bit */
+#define R_SPARC_6              45      /* Direct 6 bit */
+#define R_SPARC_DISP64         46      /* PC relative 64 bit */
+#define R_SPARC_PLT64          47      /* Direct 64 bit ref to PLT entry */
+#define R_SPARC_HIX22          48      /* High 22 bit complemented */
+#define R_SPARC_LOX10          49      /* Truncated 11 bit complemented */
+#define R_SPARC_H44            50      /* Direct high 12 of 44 bit */
+#define R_SPARC_M44            51      /* Direct mid 22 of 44 bit */
+#define R_SPARC_L44            52      /* Direct low 10 of 44 bit */
+#define R_SPARC_REGISTER       53      /* Global register usage */
+#define R_SPARC_UA64           54      /* Direct 64 bit unaligned */
+#define R_SPARC_UA16           55      /* Direct 16 bit unaligned */
+#define R_SPARC_TLS_GD_HI22    56
+#define R_SPARC_TLS_GD_LO10    57
+#define R_SPARC_TLS_GD_ADD     58
+#define R_SPARC_TLS_GD_CALL    59
+#define R_SPARC_TLS_LDM_HI22   60
+#define R_SPARC_TLS_LDM_LO10   61
+#define R_SPARC_TLS_LDM_ADD    62
+#define R_SPARC_TLS_LDM_CALL   63
+#define R_SPARC_TLS_LDO_HIX22  64
+#define R_SPARC_TLS_LDO_LOX10  65
+#define R_SPARC_TLS_LDO_ADD    66
+#define R_SPARC_TLS_IE_HI22    67
+#define R_SPARC_TLS_IE_LO10    68
+#define R_SPARC_TLS_IE_LD      69
+#define R_SPARC_TLS_IE_LDX     70
+#define R_SPARC_TLS_IE_ADD     71
+#define R_SPARC_TLS_LE_HIX22   72
+#define R_SPARC_TLS_LE_LOX10   73
+#define R_SPARC_TLS_DTPMOD32   74
+#define R_SPARC_TLS_DTPMOD64   75
+#define R_SPARC_TLS_DTPOFF32   76
+#define R_SPARC_TLS_DTPOFF64   77
+#define R_SPARC_TLS_TPOFF32    78
+#define R_SPARC_TLS_TPOFF64    79
+/* Keep this the last entry.  */
+#define R_SPARC_NUM            80
+
+/* For Sparc64, legal values for d_tag of Elf64_Dyn.  */
+
+#define DT_SPARC_REGISTER 0x70000001
+#define DT_SPARC_NUM   2
+
+/* Bits present in AT_HWCAP, primarily for Sparc32.  */
+
+#define HWCAP_SPARC_FLUSH      1       /* The cpu supports flush insn.  */
+#define HWCAP_SPARC_STBAR      2
+#define HWCAP_SPARC_SWAP       4
+#define HWCAP_SPARC_MULDIV     8
+#define HWCAP_SPARC_V9         16      /* The cpu is v9, so v8plus is ok.  */
+#define HWCAP_SPARC_ULTRA3     32
+
+/* MIPS R3000 specific definitions.  */
+
+/* Legal values for e_flags field of Elf32_Ehdr.  */
+
+#define EF_MIPS_NOREORDER   1          /* A .noreorder directive was used */
+#define EF_MIPS_PIC        2           /* Contains PIC code */
+#define EF_MIPS_CPIC       4           /* Uses PIC calling sequence */
+#define EF_MIPS_XGOT       8
+#define EF_MIPS_64BIT_WHIRL 16
+#define EF_MIPS_ABI2       32
+#define EF_MIPS_ABI_ON32    64
+#define EF_MIPS_ARCH       0xf0000000  /* MIPS architecture level */
+
+/* Legal values for MIPS architecture level.  */
+
+#define EF_MIPS_ARCH_1     0x00000000  /* -mips1 code.  */
+#define EF_MIPS_ARCH_2     0x10000000  /* -mips2 code.  */
+#define EF_MIPS_ARCH_3     0x20000000  /* -mips3 code.  */
+#define EF_MIPS_ARCH_4     0x30000000  /* -mips4 code.  */
+#define EF_MIPS_ARCH_5     0x40000000  /* -mips5 code.  */
+#define EF_MIPS_ARCH_32            0x60000000  /* MIPS32 code.  */
+#define EF_MIPS_ARCH_64            0x70000000  /* MIPS64 code.  */
+
+/* The following are non-official names and should not be used.  */
+
+#define E_MIPS_ARCH_1    0x00000000    /* -mips1 code.  */
+#define E_MIPS_ARCH_2    0x10000000    /* -mips2 code.  */
+#define E_MIPS_ARCH_3    0x20000000    /* -mips3 code.  */
+#define E_MIPS_ARCH_4    0x30000000    /* -mips4 code.  */
+#define E_MIPS_ARCH_5    0x40000000    /* -mips5 code.  */
+#define E_MIPS_ARCH_32   0x60000000    /* MIPS32 code.  */
+#define E_MIPS_ARCH_64   0x70000000    /* MIPS64 code.  */
+
+/* Special section indices.  */
+
+#define SHN_MIPS_ACOMMON    0xff00     /* Allocated common symbols */
+#define SHN_MIPS_TEXT      0xff01      /* Allocated test symbols.  */
+#define SHN_MIPS_DATA      0xff02      /* Allocated data symbols.  */
+#define SHN_MIPS_SCOMMON    0xff03     /* Small common symbols */
+#define SHN_MIPS_SUNDEFINED 0xff04     /* Small undefined symbols */
+
+/* Legal values for sh_type field of Elf32_Shdr.  */
+
+#define SHT_MIPS_LIBLIST       0x70000000 /* Shared objects used in link */
+#define SHT_MIPS_MSYM         0x70000001
+#define SHT_MIPS_CONFLICT      0x70000002 /* Conflicting symbols */
+#define SHT_MIPS_GPTAB        0x70000003 /* Global data area sizes */
+#define SHT_MIPS_UCODE        0x70000004 /* Reserved for SGI/MIPS compilers */
+#define SHT_MIPS_DEBUG        0x70000005 /* MIPS ECOFF debugging information*/
+#define SHT_MIPS_REGINFO       0x70000006 /* Register usage information */
+#define SHT_MIPS_PACKAGE       0x70000007
+#define SHT_MIPS_PACKSYM       0x70000008
+#define SHT_MIPS_RELD         0x70000009
+#define SHT_MIPS_IFACE         0x7000000b
+#define SHT_MIPS_CONTENT       0x7000000c
+#define SHT_MIPS_OPTIONS       0x7000000d /* Miscellaneous options.  */
+#define SHT_MIPS_SHDR         0x70000010
+#define SHT_MIPS_FDESC        0x70000011
+#define SHT_MIPS_EXTSYM               0x70000012
+#define SHT_MIPS_DENSE        0x70000013
+#define SHT_MIPS_PDESC        0x70000014
+#define SHT_MIPS_LOCSYM               0x70000015
+#define SHT_MIPS_AUXSYM               0x70000016
+#define SHT_MIPS_OPTSYM               0x70000017
+#define SHT_MIPS_LOCSTR               0x70000018
+#define SHT_MIPS_LINE         0x70000019
+#define SHT_MIPS_RFDESC               0x7000001a
+#define SHT_MIPS_DELTASYM      0x7000001b
+#define SHT_MIPS_DELTAINST     0x7000001c
+#define SHT_MIPS_DELTACLASS    0x7000001d
+#define SHT_MIPS_DWARF         0x7000001e /* DWARF debugging information.  */
+#define SHT_MIPS_DELTADECL     0x7000001f
+#define SHT_MIPS_SYMBOL_LIB    0x70000020
+#define SHT_MIPS_EVENTS               0x70000021 /* Event section.  */
+#define SHT_MIPS_TRANSLATE     0x70000022
+#define SHT_MIPS_PIXIE        0x70000023
+#define SHT_MIPS_XLATE        0x70000024
+#define SHT_MIPS_XLATE_DEBUG   0x70000025
+#define SHT_MIPS_WHIRL        0x70000026
+#define SHT_MIPS_EH_REGION     0x70000027
+#define SHT_MIPS_XLATE_OLD     0x70000028
+#define SHT_MIPS_PDR_EXCEPTION 0x70000029
+
+/* Legal values for sh_flags field of Elf32_Shdr.  */
+
+#define SHF_MIPS_GPREL  0x10000000     /* Must be part of global data area */
+#define SHF_MIPS_MERGE  0x20000000
+#define SHF_MIPS_ADDR   0x40000000
+#define SHF_MIPS_STRINGS 0x80000000
+#define SHF_MIPS_NOSTRIP 0x08000000
+#define SHF_MIPS_LOCAL  0x04000000
+#define SHF_MIPS_NAMES  0x02000000
+#define SHF_MIPS_NODUPE         0x01000000
+
+
+/* Symbol tables.  */
+
+/* MIPS specific values for `st_other'.  */
+#define STO_MIPS_DEFAULT               0x0
+#define STO_MIPS_INTERNAL              0x1
+#define STO_MIPS_HIDDEN                        0x2
+#define STO_MIPS_PROTECTED             0x3
+#define STO_MIPS_SC_ALIGN_UNUSED       0xff
+
+/* MIPS specific values for `st_info'.  */
+#define STB_MIPS_SPLIT_COMMON          13
+
+/* Entries found in sections of type SHT_MIPS_GPTAB.  */
+
+typedef union
+{
+  struct
+    {
+      Elf32_Word gt_current_g_value;   /* -G value used for compilation */
+      Elf32_Word gt_unused;            /* Not used */
+    } gt_header;                       /* First entry in section */
+  struct
+    {
+      Elf32_Word gt_g_value;           /* If this value were used for -G */
+      Elf32_Word gt_bytes;             /* This many bytes would be used */
+    } gt_entry;                                /* Subsequent entries in section */
+} Elf32_gptab;
+
+/* Entry found in sections of type SHT_MIPS_REGINFO.  */
+
+typedef struct
+{
+  Elf32_Word   ri_gprmask;             /* General registers used */
+  Elf32_Word   ri_cprmask[4];          /* Coprocessor registers used */
+  Elf32_Sword  ri_gp_value;            /* $gp register value */
+} Elf32_RegInfo;
+
+/* Entries found in sections of type SHT_MIPS_OPTIONS.  */
+
+typedef struct
+{
+  unsigned char kind;          /* Determines interpretation of the
+                                  variable part of descriptor.  */
+  unsigned char size;          /* Size of descriptor, including header.  */
+  Elf32_Section section;       /* Section header index of section affected,
+                                  0 for global options.  */
+  Elf32_Word info;             /* Kind-specific information.  */
+} Elf_Options;
+
+/* Values for `kind' field in Elf_Options.  */
+
+#define ODK_NULL       0       /* Undefined.  */
+#define ODK_REGINFO    1       /* Register usage information.  */
+#define ODK_EXCEPTIONS 2       /* Exception processing options.  */
+#define ODK_PAD                3       /* Section padding options.  */
+#define ODK_HWPATCH    4       /* Hardware workarounds performed */
+#define ODK_FILL       5       /* record the fill value used by the linker. */
+#define ODK_TAGS       6       /* reserve space for desktop tools to write. */
+#define ODK_HWAND      7       /* HW workarounds.  'AND' bits when merging. */
+#define ODK_HWOR       8       /* HW workarounds.  'OR' bits when merging.  */
+
+/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries.  */
+
+#define OEX_FPU_MIN    0x1f    /* FPE's which MUST be enabled.  */
+#define OEX_FPU_MAX    0x1f00  /* FPE's which MAY be enabled.  */
+#define OEX_PAGE0      0x10000 /* page zero must be mapped.  */
+#define OEX_SMM                0x20000 /* Force sequential memory mode?  */
+#define OEX_FPDBUG     0x40000 /* Force floating point debug mode?  */
+#define OEX_PRECISEFP  OEX_FPDBUG
+#define OEX_DISMISS    0x80000 /* Dismiss invalid address faults?  */
+
+#define OEX_FPU_INVAL  0x10
+#define OEX_FPU_DIV0   0x08
+#define OEX_FPU_OFLO   0x04
+#define OEX_FPU_UFLO   0x02
+#define OEX_FPU_INEX   0x01
+
+/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry.  */
+
+#define OHW_R4KEOP     0x1     /* R4000 end-of-page patch.  */
+#define OHW_R8KPFETCH  0x2     /* may need R8000 prefetch patch.  */
+#define OHW_R5KEOP     0x4     /* R5000 end-of-page patch.  */
+#define OHW_R5KCVTL    0x8     /* R5000 cvt.[ds].l bug.  clean=1.  */
+
+#define OPAD_PREFIX    0x1
+#define OPAD_POSTFIX   0x2
+#define OPAD_SYMBOL    0x4
+
+/* Entry found in `.options' section.  */
+
+typedef struct
+{
+  Elf32_Word hwp_flags1;       /* Extra flags.  */
+  Elf32_Word hwp_flags2;       /* Extra flags.  */
+} Elf_Options_Hw;
+
+/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries.  */
+
+#define OHWA0_R4KEOP_CHECKED   0x00000001
+#define OHWA1_R4KEOP_CLEAN     0x00000002
+
+/* MIPS relocs.  */
+
+#define R_MIPS_NONE            0       /* No reloc */
+#define R_MIPS_16              1       /* Direct 16 bit */
+#define R_MIPS_32              2       /* Direct 32 bit */
+#define R_MIPS_REL32           3       /* PC relative 32 bit */
+#define R_MIPS_26              4       /* Direct 26 bit shifted */
+#define R_MIPS_HI16            5       /* High 16 bit */
+#define R_MIPS_LO16            6       /* Low 16 bit */
+#define R_MIPS_GPREL16         7       /* GP relative 16 bit */
+#define R_MIPS_LITERAL         8       /* 16 bit literal entry */
+#define R_MIPS_GOT16           9       /* 16 bit GOT entry */
+#define R_MIPS_PC16            10      /* PC relative 16 bit */
+#define R_MIPS_CALL16          11      /* 16 bit GOT entry for function */
+#define R_MIPS_GPREL32         12      /* GP relative 32 bit */
+
+#define R_MIPS_SHIFT5          16
+#define R_MIPS_SHIFT6          17
+#define R_MIPS_64              18
+#define R_MIPS_GOT_DISP                19
+#define R_MIPS_GOT_PAGE                20
+#define R_MIPS_GOT_OFST                21
+#define R_MIPS_GOT_HI16                22
+#define R_MIPS_GOT_LO16                23
+#define R_MIPS_SUB             24
+#define R_MIPS_INSERT_A                25
+#define R_MIPS_INSERT_B                26
+#define R_MIPS_DELETE          27
+#define R_MIPS_HIGHER          28
+#define R_MIPS_HIGHEST         29
+#define R_MIPS_CALL_HI16       30
+#define R_MIPS_CALL_LO16       31
+#define R_MIPS_SCN_DISP                32
+#define R_MIPS_REL16           33
+#define R_MIPS_ADD_IMMEDIATE   34
+#define R_MIPS_PJUMP           35
+#define R_MIPS_RELGOT          36
+#define R_MIPS_JALR            37
+/* Keep this the last entry.  */
+#define R_MIPS_NUM             38
+
+/* Legal values for p_type field of Elf32_Phdr.  */
+
+#define PT_MIPS_REGINFO        0x70000000      /* Register usage information */
+#define PT_MIPS_RTPROC  0x70000001     /* Runtime procedure table. */
+#define PT_MIPS_OPTIONS 0x70000002
+
+/* Special program header types.  */
+
+#define PF_MIPS_LOCAL  0x10000000
+
+/* Legal values for d_tag field of Elf32_Dyn.  */
+
+#define DT_MIPS_RLD_VERSION  0x70000001        /* Runtime linker interface version */
+#define DT_MIPS_TIME_STAMP   0x70000002        /* Timestamp */
+#define DT_MIPS_ICHECKSUM    0x70000003        /* Checksum */
+#define DT_MIPS_IVERSION     0x70000004        /* Version string (string tbl index) */
+#define DT_MIPS_FLAGS       0x70000005 /* Flags */
+#define DT_MIPS_BASE_ADDRESS 0x70000006        /* Base address */
+#define DT_MIPS_MSYM        0x70000007
+#define DT_MIPS_CONFLICT     0x70000008        /* Address of CONFLICT section */
+#define DT_MIPS_LIBLIST             0x70000009 /* Address of LIBLIST section */
+#define DT_MIPS_LOCAL_GOTNO  0x7000000a        /* Number of local GOT entries */
+#define DT_MIPS_CONFLICTNO   0x7000000b        /* Number of CONFLICT entries */
+#define DT_MIPS_LIBLISTNO    0x70000010        /* Number of LIBLIST entries */
+#define DT_MIPS_SYMTABNO     0x70000011        /* Number of DYNSYM entries */
+#define DT_MIPS_UNREFEXTNO   0x70000012        /* First external DYNSYM */
+#define DT_MIPS_GOTSYM      0x70000013 /* First GOT entry in DYNSYM */
+#define DT_MIPS_HIPAGENO     0x70000014        /* Number of GOT page table entries */
+#define DT_MIPS_RLD_MAP             0x70000016 /* Address of run time loader map.  */
+#define DT_MIPS_DELTA_CLASS  0x70000017        /* Delta C++ class definition.  */
+#define DT_MIPS_DELTA_CLASS_NO    0x70000018 /* Number of entries in
+                                               DT_MIPS_DELTA_CLASS.  */
+#define DT_MIPS_DELTA_INSTANCE    0x70000019 /* Delta C++ class instances.  */
+#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in
+                                               DT_MIPS_DELTA_INSTANCE.  */
+#define DT_MIPS_DELTA_RELOC  0x7000001b /* Delta relocations.  */
+#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in
+                                            DT_MIPS_DELTA_RELOC.  */
+#define DT_MIPS_DELTA_SYM    0x7000001d /* Delta symbols that Delta
+                                          relocations refer to.  */
+#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in
+                                          DT_MIPS_DELTA_SYM.  */
+#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the
+                                            class declaration.  */
+#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in
+                                               DT_MIPS_DELTA_CLASSSYM.  */
+#define DT_MIPS_CXX_FLAGS    0x70000022 /* Flags indicating for C++ flavor.  */
+#define DT_MIPS_PIXIE_INIT   0x70000023
+#define DT_MIPS_SYMBOL_LIB   0x70000024
+#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
+#define DT_MIPS_LOCAL_GOTIDX 0x70000026
+#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
+#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
+#define DT_MIPS_OPTIONS             0x70000029 /* Address of .options.  */
+#define DT_MIPS_INTERFACE    0x7000002a /* Address of .interface.  */
+#define DT_MIPS_DYNSTR_ALIGN 0x7000002b
+#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */
+#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve
+                                                   function stored in GOT.  */
+#define DT_MIPS_PERF_SUFFIX  0x7000002e /* Default suffix of dso to be added
+                                          by rld on dlopen() calls.  */
+#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */
+#define DT_MIPS_GP_VALUE     0x70000030 /* GP value for aux GOTs.  */
+#define DT_MIPS_AUX_DYNAMIC  0x70000031 /* Address of aux .dynamic.  */
+#define DT_MIPS_NUM         0x32
+
+/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry.  */
+
+#define RHF_NONE                  0            /* No flags */
+#define RHF_QUICKSTART            (1 << 0)     /* Use quickstart */
+#define RHF_NOTPOT                (1 << 1)     /* Hash size not power of 2 */
+#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2)    /* Ignore LD_LIBRARY_PATH */
+#define RHF_NO_MOVE               (1 << 3)
+#define RHF_SGI_ONLY              (1 << 4)
+#define RHF_GUARANTEE_INIT        (1 << 5)
+#define RHF_DELTA_C_PLUS_PLUS     (1 << 6)
+#define RHF_GUARANTEE_START_INIT   (1 << 7)
+#define RHF_PIXIE                 (1 << 8)
+#define RHF_DEFAULT_DELAY_LOAD    (1 << 9)
+#define RHF_REQUICKSTART          (1 << 10)
+#define RHF_REQUICKSTARTED        (1 << 11)
+#define RHF_CORD                  (1 << 12)
+#define RHF_NO_UNRES_UNDEF        (1 << 13)
+#define RHF_RLD_ORDER_SAFE        (1 << 14)
+
+/* Entries found in sections of type SHT_MIPS_LIBLIST.  */
+
+typedef struct
+{
+  Elf32_Word l_name;           /* Name (string table index) */
+  Elf32_Word l_time_stamp;     /* Timestamp */
+  Elf32_Word l_checksum;       /* Checksum */
+  Elf32_Word l_version;                /* Interface version */
+  Elf32_Word l_flags;          /* Flags */
+} Elf32_Lib;
+
+typedef struct
+{
+  Elf64_Word l_name;           /* Name (string table index) */
+  Elf64_Word l_time_stamp;     /* Timestamp */
+  Elf64_Word l_checksum;       /* Checksum */
+  Elf64_Word l_version;                /* Interface version */
+  Elf64_Word l_flags;          /* Flags */
+} Elf64_Lib;
+
+
+/* Legal values for l_flags.  */
+
+#define LL_NONE                  0
+#define LL_EXACT_MATCH   (1 << 0)      /* Require exact match */
+#define LL_IGNORE_INT_VER (1 << 1)     /* Ignore interface version */
+#define LL_REQUIRE_MINOR  (1 << 2)
+#define LL_EXPORTS       (1 << 3)
+#define LL_DELAY_LOAD    (1 << 4)
+#define LL_DELTA         (1 << 5)
+
+/* Entries found in sections of type SHT_MIPS_CONFLICT.  */
+
+typedef Elf32_Addr Elf32_Conflict;
+
+
+/* HPPA specific definitions.  */
+
+/* Legal values for e_flags field of Elf32_Ehdr.  */
+
+#define EF_PARISC_TRAPNIL      0x00010000 /* Trap nil pointer dereference.  */
+#define EF_PARISC_EXT          0x00020000 /* Program uses arch. extensions. */
+#define EF_PARISC_LSB          0x00040000 /* Program expects little endian. */
+#define EF_PARISC_WIDE         0x00080000 /* Program expects wide mode.  */
+#define EF_PARISC_NO_KABP      0x00100000 /* No kernel assisted branch
+                                             prediction.  */
+#define EF_PARISC_LAZYSWAP     0x00400000 /* Allow lazy swapping.  */
+#define EF_PARISC_ARCH         0x0000ffff /* Architecture version.  */
+
+/* Defined values for `e_flags & EF_PARISC_ARCH' are:  */
+
+#define EFA_PARISC_1_0             0x020b /* PA-RISC 1.0 big-endian.  */
+#define EFA_PARISC_1_1             0x0210 /* PA-RISC 1.1 big-endian.  */
+#define EFA_PARISC_2_0             0x0214 /* PA-RISC 2.0 big-endian.  */
+
+/* Additional section indeces.  */
+
+#define SHN_PARISC_ANSI_COMMON 0xff00     /* Section for tenatively declared
+                                             symbols in ANSI C.  */
+#define SHN_PARISC_HUGE_COMMON 0xff01     /* Common blocks in huge model.  */
+
+/* Legal values for sh_type field of Elf32_Shdr.  */
+
+#define SHT_PARISC_EXT         0x70000000 /* Contains product specific ext. */
+#define SHT_PARISC_UNWIND      0x70000001 /* Unwind information.  */
+#define SHT_PARISC_DOC         0x70000002 /* Debug info for optimized code. */
+
+/* Legal values for sh_flags field of Elf32_Shdr.  */
+
+#define SHF_PARISC_SHORT       0x20000000 /* Section with short addressing. */
+#define SHF_PARISC_HUGE                0x40000000 /* Section far from gp.  */
+#define SHF_PARISC_SBP         0x80000000 /* Static branch prediction code. */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
+
+#define STT_PARISC_MILLICODE   13      /* Millicode function entry point.  */
+
+#define STT_HP_OPAQUE          (STT_LOOS + 0x1)
+#define STT_HP_STUB            (STT_LOOS + 0x2)
+
+/* HPPA relocs.  */
+
+#define R_PARISC_NONE          0       /* No reloc.  */
+#define R_PARISC_DIR32         1       /* Direct 32-bit reference.  */
+#define R_PARISC_DIR21L                2       /* Left 21 bits of eff. address.  */
+#define R_PARISC_DIR17R                3       /* Right 17 bits of eff. address.  */
+#define R_PARISC_DIR17F                4       /* 17 bits of eff. address.  */
+#define R_PARISC_DIR14R                6       /* Right 14 bits of eff. address.  */
+#define R_PARISC_PCREL32       9       /* 32-bit rel. address.  */
+#define R_PARISC_PCREL21L      10      /* Left 21 bits of rel. address.  */
+#define R_PARISC_PCREL17R      11      /* Right 17 bits of rel. address.  */
+#define R_PARISC_PCREL17F      12      /* 17 bits of rel. address.  */
+#define R_PARISC_PCREL14R      14      /* Right 14 bits of rel. address.  */
+#define R_PARISC_DPREL21L      18      /* Left 21 bits of rel. address.  */
+#define R_PARISC_DPREL14R      22      /* Right 14 bits of rel. address.  */
+#define R_PARISC_GPREL21L      26      /* GP-relative, left 21 bits.  */
+#define R_PARISC_GPREL14R      30      /* GP-relative, right 14 bits.  */
+#define R_PARISC_LTOFF21L      34      /* LT-relative, left 21 bits.  */
+#define R_PARISC_LTOFF14R      38      /* LT-relative, right 14 bits.  */
+#define R_PARISC_SECREL32      41      /* 32 bits section rel. address.  */
+#define R_PARISC_SEGBASE       48      /* No relocation, set segment base.  */
+#define R_PARISC_SEGREL32      49      /* 32 bits segment rel. address.  */
+#define R_PARISC_PLTOFF21L     50      /* PLT rel. address, left 21 bits.  */
+#define R_PARISC_PLTOFF14R     54      /* PLT rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF_FPTR32  57      /* 32 bits LT-rel. function pointer. */
+#define R_PARISC_LTOFF_FPTR21L 58      /* LT-rel. fct ptr, left 21 bits. */
+#define R_PARISC_LTOFF_FPTR14R 62      /* LT-rel. fct ptr, right 14 bits. */
+#define R_PARISC_FPTR64                64      /* 64 bits function address.  */
+#define R_PARISC_PLABEL32      65      /* 32 bits function address.  */
+#define R_PARISC_PCREL64       72      /* 64 bits PC-rel. address.  */
+#define R_PARISC_PCREL22F      74      /* 22 bits PC-rel. address.  */
+#define R_PARISC_PCREL14WR     75      /* PC-rel. address, right 14 bits.  */
+#define R_PARISC_PCREL14DR     76      /* PC rel. address, right 14 bits.  */
+#define R_PARISC_PCREL16F      77      /* 16 bits PC-rel. address.  */
+#define R_PARISC_PCREL16WF     78      /* 16 bits PC-rel. address.  */
+#define R_PARISC_PCREL16DF     79      /* 16 bits PC-rel. address.  */
+#define R_PARISC_DIR64         80      /* 64 bits of eff. address.  */
+#define R_PARISC_DIR14WR       83      /* 14 bits of eff. address.  */
+#define R_PARISC_DIR14DR       84      /* 14 bits of eff. address.  */
+#define R_PARISC_DIR16F                85      /* 16 bits of eff. address.  */
+#define R_PARISC_DIR16WF       86      /* 16 bits of eff. address.  */
+#define R_PARISC_DIR16DF       87      /* 16 bits of eff. address.  */
+#define R_PARISC_GPREL64       88      /* 64 bits of GP-rel. address.  */
+#define R_PARISC_GPREL14WR     91      /* GP-rel. address, right 14 bits.  */
+#define R_PARISC_GPREL14DR     92      /* GP-rel. address, right 14 bits.  */
+#define R_PARISC_GPREL16F      93      /* 16 bits GP-rel. address.  */
+#define R_PARISC_GPREL16WF     94      /* 16 bits GP-rel. address.  */
+#define R_PARISC_GPREL16DF     95      /* 16 bits GP-rel. address.  */
+#define R_PARISC_LTOFF64       96      /* 64 bits LT-rel. address.  */
+#define R_PARISC_LTOFF14WR     99      /* LT-rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF14DR     100     /* LT-rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF16F      101     /* 16 bits LT-rel. address.  */
+#define R_PARISC_LTOFF16WF     102     /* 16 bits LT-rel. address.  */
+#define R_PARISC_LTOFF16DF     103     /* 16 bits LT-rel. address.  */
+#define R_PARISC_SECREL64      104     /* 64 bits section rel. address.  */
+#define R_PARISC_SEGREL64      112     /* 64 bits segment rel. address.  */
+#define R_PARISC_PLTOFF14WR    115     /* PLT-rel. address, right 14 bits.  */
+#define R_PARISC_PLTOFF14DR    116     /* PLT-rel. address, right 14 bits.  */
+#define R_PARISC_PLTOFF16F     117     /* 16 bits LT-rel. address.  */
+#define R_PARISC_PLTOFF16WF    118     /* 16 bits PLT-rel. address.  */
+#define R_PARISC_PLTOFF16DF    119     /* 16 bits PLT-rel. address.  */
+#define R_PARISC_LTOFF_FPTR64  120     /* 64 bits LT-rel. function ptr.  */
+#define R_PARISC_LTOFF_FPTR14WR        123     /* LT-rel. fct. ptr., right 14 bits. */
+#define R_PARISC_LTOFF_FPTR14DR        124     /* LT-rel. fct. ptr., right 14 bits. */
+#define R_PARISC_LTOFF_FPTR16F 125     /* 16 bits LT-rel. function ptr.  */
+#define R_PARISC_LTOFF_FPTR16WF        126     /* 16 bits LT-rel. function ptr.  */
+#define R_PARISC_LTOFF_FPTR16DF        127     /* 16 bits LT-rel. function ptr.  */
+#define R_PARISC_LORESERVE     128
+#define R_PARISC_COPY          128     /* Copy relocation.  */
+#define R_PARISC_IPLT          129     /* Dynamic reloc, imported PLT */
+#define R_PARISC_EPLT          130     /* Dynamic reloc, exported PLT */
+#define R_PARISC_TPREL32       153     /* 32 bits TP-rel. address.  */
+#define R_PARISC_TPREL21L      154     /* TP-rel. address, left 21 bits.  */
+#define R_PARISC_TPREL14R      158     /* TP-rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF_TP21L   162     /* LT-TP-rel. address, left 21 bits. */
+#define R_PARISC_LTOFF_TP14R   166     /* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP14F   167     /* 14 bits LT-TP-rel. address.  */
+#define R_PARISC_TPREL64       216     /* 64 bits TP-rel. address.  */
+#define R_PARISC_TPREL14WR     219     /* TP-rel. address, right 14 bits.  */
+#define R_PARISC_TPREL14DR     220     /* TP-rel. address, right 14 bits.  */
+#define R_PARISC_TPREL16F      221     /* 16 bits TP-rel. address.  */
+#define R_PARISC_TPREL16WF     222     /* 16 bits TP-rel. address.  */
+#define R_PARISC_TPREL16DF     223     /* 16 bits TP-rel. address.  */
+#define R_PARISC_LTOFF_TP64    224     /* 64 bits LT-TP-rel. address.  */
+#define R_PARISC_LTOFF_TP14WR  227     /* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP14DR  228     /* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP16F   229     /* 16 bits LT-TP-rel. address.  */
+#define R_PARISC_LTOFF_TP16WF  230     /* 16 bits LT-TP-rel. address.  */
+#define R_PARISC_LTOFF_TP16DF  231     /* 16 bits LT-TP-rel. address.  */
+#define R_PARISC_HIRESERVE     255
+
+/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr.  */
+
+#define PT_HP_TLS              (PT_LOOS + 0x0)
+#define PT_HP_CORE_NONE                (PT_LOOS + 0x1)
+#define PT_HP_CORE_VERSION     (PT_LOOS + 0x2)
+#define PT_HP_CORE_KERNEL      (PT_LOOS + 0x3)
+#define PT_HP_CORE_COMM                (PT_LOOS + 0x4)
+#define PT_HP_CORE_PROC                (PT_LOOS + 0x5)
+#define PT_HP_CORE_LOADABLE    (PT_LOOS + 0x6)
+#define PT_HP_CORE_STACK       (PT_LOOS + 0x7)
+#define PT_HP_CORE_SHM         (PT_LOOS + 0x8)
+#define PT_HP_CORE_MMF         (PT_LOOS + 0x9)
+#define PT_HP_PARALLEL         (PT_LOOS + 0x10)
+#define PT_HP_FASTBIND         (PT_LOOS + 0x11)
+#define PT_HP_OPT_ANNOT                (PT_LOOS + 0x12)
+#define PT_HP_HSL_ANNOT                (PT_LOOS + 0x13)
+#define PT_HP_STACK            (PT_LOOS + 0x14)
+
+#define PT_PARISC_ARCHEXT      0x70000000
+#define PT_PARISC_UNWIND       0x70000001
+
+/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr.  */
+
+#define PF_PARISC_SBP          0x08000000
+
+#define PF_HP_PAGE_SIZE                0x00100000
+#define PF_HP_FAR_SHARED       0x00200000
+#define PF_HP_NEAR_SHARED      0x00400000
+#define PF_HP_CODE             0x01000000
+#define PF_HP_MODIFY           0x02000000
+#define PF_HP_LAZYSWAP         0x04000000
+#define PF_HP_SBP              0x08000000
+
+
+/* Alpha specific definitions.  */
+
+/* Legal values for e_flags field of Elf64_Ehdr.  */
+
+#define EF_ALPHA_32BIT         1       /* All addresses must be < 2GB.  */
+#define EF_ALPHA_CANRELAX      2       /* Relocations for relaxing exist.  */
+
+/* Legal values for sh_type field of Elf64_Shdr.  */
+
+/* These two are primerily concerned with ECOFF debugging info.  */
+#define SHT_ALPHA_DEBUG                0x70000001
+#define SHT_ALPHA_REGINFO      0x70000002
+
+/* Legal values for sh_flags field of Elf64_Shdr.  */
+
+#define SHF_ALPHA_GPREL                0x10000000
+
+/* Legal values for st_other field of Elf64_Sym.  */
+#define STO_ALPHA_NOPV         0x80    /* No PV required.  */
+#define STO_ALPHA_STD_GPLOAD   0x88    /* PV only used for initial ldgp.  */
+
+/* Alpha relocs.  */
+
+#define R_ALPHA_NONE           0       /* No reloc */
+#define R_ALPHA_REFLONG                1       /* Direct 32 bit */
+#define R_ALPHA_REFQUAD                2       /* Direct 64 bit */
+#define R_ALPHA_GPREL32                3       /* GP relative 32 bit */
+#define R_ALPHA_LITERAL                4       /* GP relative 16 bit w/optimization */
+#define R_ALPHA_LITUSE         5       /* Optimization hint for LITERAL */
+#define R_ALPHA_GPDISP         6       /* Add displacement to GP */
+#define R_ALPHA_BRADDR         7       /* PC+4 relative 23 bit shifted */
+#define R_ALPHA_HINT           8       /* PC+4 relative 16 bit shifted */
+#define R_ALPHA_SREL16         9       /* PC relative 16 bit */
+#define R_ALPHA_SREL32         10      /* PC relative 32 bit */
+#define R_ALPHA_SREL64         11      /* PC relative 64 bit */
+#define R_ALPHA_GPRELHIGH      17      /* GP relative 32 bit, high 16 bits */
+#define R_ALPHA_GPRELLOW       18      /* GP relative 32 bit, low 16 bits */
+#define R_ALPHA_GPREL16                19      /* GP relative 16 bit */
+#define R_ALPHA_COPY           24      /* Copy symbol at runtime */
+#define R_ALPHA_GLOB_DAT       25      /* Create GOT entry */
+#define R_ALPHA_JMP_SLOT       26      /* Create PLT entry */
+#define R_ALPHA_RELATIVE       27      /* Adjust by program base */
+#define R_ALPHA_TLS_GD_HI      28
+#define R_ALPHA_TLSGD          29
+#define R_ALPHA_TLS_LDM                30
+#define R_ALPHA_DTPMOD64       31
+#define R_ALPHA_GOTDTPREL      32
+#define R_ALPHA_DTPREL64       33
+#define R_ALPHA_DTPRELHI       34
+#define R_ALPHA_DTPRELLO       35
+#define R_ALPHA_DTPREL16       36
+#define R_ALPHA_GOTTPREL       37
+#define R_ALPHA_TPREL64                38
+#define R_ALPHA_TPRELHI                39
+#define R_ALPHA_TPRELLO                40
+#define R_ALPHA_TPREL16                41
+/* Keep this the last entry.  */
+#define R_ALPHA_NUM            46
+
+/* Magic values of the LITUSE relocation addend.  */
+#define LITUSE_ALPHA_ADDR      0
+#define LITUSE_ALPHA_BASE      1
+#define LITUSE_ALPHA_BYTOFF    2
+#define LITUSE_ALPHA_JSR       3
+#define LITUSE_ALPHA_TLS_GD    4
+#define LITUSE_ALPHA_TLS_LDM   5
+
+
+/* PowerPC specific declarations */
+
+/* Values for Elf32/64_Ehdr.e_flags.  */
+#define EF_PPC_EMB             0x80000000      /* PowerPC embedded flag */
+
+/* Cygnus local bits below */
+#define EF_PPC_RELOCATABLE     0x00010000      /* PowerPC -mrelocatable flag*/
+#define EF_PPC_RELOCATABLE_LIB 0x00008000      /* PowerPC -mrelocatable-lib
+                                                  flag */
+
+/* PowerPC relocations defined by the ABIs */
+#define R_PPC_NONE             0
+#define R_PPC_ADDR32           1       /* 32bit absolute address */
+#define R_PPC_ADDR24           2       /* 26bit address, 2 bits ignored.  */
+#define R_PPC_ADDR16           3       /* 16bit absolute address */
+#define R_PPC_ADDR16_LO                4       /* lower 16bit of absolute address */
+#define R_PPC_ADDR16_HI                5       /* high 16bit of absolute address */
+#define R_PPC_ADDR16_HA                6       /* adjusted high 16bit */
+#define R_PPC_ADDR14           7       /* 16bit address, 2 bits ignored */
+#define R_PPC_ADDR14_BRTAKEN   8
+#define R_PPC_ADDR14_BRNTAKEN  9
+#define R_PPC_REL24            10      /* PC relative 26 bit */
+#define R_PPC_REL14            11      /* PC relative 16 bit */
+#define R_PPC_REL14_BRTAKEN    12
+#define R_PPC_REL14_BRNTAKEN   13
+#define R_PPC_GOT16            14
+#define R_PPC_GOT16_LO         15
+#define R_PPC_GOT16_HI         16
+#define R_PPC_GOT16_HA         17
+#define R_PPC_PLTREL24         18
+#define R_PPC_COPY             19
+#define R_PPC_GLOB_DAT         20
+#define R_PPC_JMP_SLOT         21
+#define R_PPC_RELATIVE         22
+#define R_PPC_LOCAL24PC                23
+#define R_PPC_UADDR32          24
+#define R_PPC_UADDR16          25
+#define R_PPC_REL32            26
+#define R_PPC_PLT32            27
+#define R_PPC_PLTREL32         28
+#define R_PPC_PLT16_LO         29
+#define R_PPC_PLT16_HI         30
+#define R_PPC_PLT16_HA         31
+#define R_PPC_SDAREL16         32
+#define R_PPC_SECTOFF          33
+#define R_PPC_SECTOFF_LO       34
+#define R_PPC_SECTOFF_HI       35
+#define R_PPC_SECTOFF_HA       36
+/* Keep this the last entry.  */
+#define R_PPC_NUM              37
+
+/* PowerPC64 relocations defined by the ABIs */
+#define R_PPC64_NONE    R_PPC_NONE
+#define R_PPC64_ADDR32  R_PPC_ADDR32  /* 32bit absolute address.  */
+#define R_PPC64_ADDR24  R_PPC_ADDR24  /* 26bit address, word aligned.  */
+#define R_PPC64_ADDR16  R_PPC_ADDR16  /* 16bit absolute address. */
+#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of abs. address.  */
+#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of abs. address. */
+#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits.  */
+#define R_PPC64_ADDR14 R_PPC_ADDR14   /* 16bit address, word aligned.  */
+#define R_PPC64_ADDR14_BRTAKEN  R_PPC_ADDR14_BRTAKEN
+#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN
+#define R_PPC64_REL24   R_PPC_REL24 /* PC relative 26 bit, word aligned.  */
+#define R_PPC64_REL14   R_PPC_REL14 /* PC relative 16 bit. */
+#define R_PPC64_REL14_BRTAKEN   R_PPC_REL14_BRTAKEN
+#define R_PPC64_REL14_BRNTAKEN  R_PPC_REL14_BRNTAKEN
+#define R_PPC64_GOT16     R_PPC_GOT16
+#define R_PPC64_GOT16_LO  R_PPC_GOT16_LO
+#define R_PPC64_GOT16_HI  R_PPC_GOT16_HI
+#define R_PPC64_GOT16_HA  R_PPC_GOT16_HA
+
+#define R_PPC64_COPY      R_PPC_COPY
+#define R_PPC64_GLOB_DAT  R_PPC_GLOB_DAT
+#define R_PPC64_JMP_SLOT  R_PPC_JMP_SLOT
+#define R_PPC64_RELATIVE  R_PPC_RELATIVE
+
+#define R_PPC64_UADDR32   R_PPC_UADDR32
+#define R_PPC64_UADDR16   R_PPC_UADDR16
+#define R_PPC64_REL32     R_PPC_REL32
+#define R_PPC64_PLT32     R_PPC_PLT32
+#define R_PPC64_PLTREL32  R_PPC_PLTREL32
+#define R_PPC64_PLT16_LO  R_PPC_PLT16_LO
+#define R_PPC64_PLT16_HI  R_PPC_PLT16_HI
+#define R_PPC64_PLT16_HA  R_PPC_PLT16_HA
+
+#define R_PPC64_SECTOFF     R_PPC_SECTOFF
+#define R_PPC64_SECTOFF_LO  R_PPC_SECTOFF_LO
+#define R_PPC64_SECTOFF_HI  R_PPC_SECTOFF_HI
+#define R_PPC64_SECTOFF_HA  R_PPC_SECTOFF_HA
+#define R_PPC64_ADDR30          37  /* word30 (S + A - P) >> 2.  */
+#define R_PPC64_ADDR64          38  /* doubleword64 S + A.  */
+#define R_PPC64_ADDR16_HIGHER   39  /* half16 #higher(S + A).  */
+#define R_PPC64_ADDR16_HIGHERA  40  /* half16 #highera(S + A).  */
+#define R_PPC64_ADDR16_HIGHEST  41  /* half16 #highest(S + A).  */
+#define R_PPC64_ADDR16_HIGHESTA 42  /* half16 #highesta(S + A). */
+#define R_PPC64_UADDR64     43  /* doubleword64 S + A.  */
+#define R_PPC64_REL64       44  /* doubleword64 S + A - P.  */
+#define R_PPC64_PLT64       45  /* doubleword64 L + A.  */
+#define R_PPC64_PLTREL64    46  /* doubleword64 L + A - P.  */
+#define R_PPC64_TOC16       47  /* half16* S + A - .TOC.  */
+#define R_PPC64_TOC16_LO    48  /* half16 #lo(S + A - .TOC.).  */
+#define R_PPC64_TOC16_HI    49  /* half16 #hi(S + A - .TOC.).  */
+#define R_PPC64_TOC16_HA    50  /* half16 #ha(S + A - .TOC.).  */
+#define R_PPC64_TOC         51  /* doubleword64 .TOC. */
+#define R_PPC64_PLTGOT16    52  /* half16* M + A.  */
+#define R_PPC64_PLTGOT16_LO 53  /* half16 #lo(M + A).  */
+#define R_PPC64_PLTGOT16_HI 54  /* half16 #hi(M + A).  */
+#define R_PPC64_PLTGOT16_HA 55  /* half16 #ha(M + A).  */
+
+#define R_PPC64_ADDR16_DS      56 /* half16ds* (S + A) >> 2.  */
+#define R_PPC64_ADDR16_LO_DS   57 /* half16ds  #lo(S + A) >> 2.  */
+#define R_PPC64_GOT16_DS       58 /* half16ds* (G + A) >> 2.  */
+#define R_PPC64_GOT16_LO_DS    59 /* half16ds  #lo(G + A) >> 2.  */
+#define R_PPC64_PLT16_LO_DS    60 /* half16ds  #lo(L + A) >> 2.  */
+#define R_PPC64_SECTOFF_DS     61 /* half16ds* (R + A) >> 2.  */
+#define R_PPC64_SECTOFF_LO_DS  62 /* half16ds  #lo(R + A) >> 2.  */
+#define R_PPC64_TOC16_DS       63 /* half16ds* (S + A - .TOC.) >> 2.  */
+#define R_PPC64_TOC16_LO_DS    64 /* half16ds  #lo(S + A - .TOC.) >> 2.  */
+#define R_PPC64_PLTGOT16_DS    65 /* half16ds* (M + A) >> 2.  */
+#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds  #lo(M + A) >> 2.  */
+/* Keep this the last entry.  */
+#define R_PPC64_NUM            67
+
+/* The remaining relocs are from the Embedded ELF ABI, and are not
+   in the SVR4 ELF ABI.  */
+#define R_PPC_EMB_NADDR32      101
+#define R_PPC_EMB_NADDR16      102
+#define R_PPC_EMB_NADDR16_LO   103
+#define R_PPC_EMB_NADDR16_HI   104
+#define R_PPC_EMB_NADDR16_HA   105
+#define R_PPC_EMB_SDAI16       106
+#define R_PPC_EMB_SDA2I16      107
+#define R_PPC_EMB_SDA2REL      108
+#define R_PPC_EMB_SDA21                109     /* 16 bit offset in SDA */
+#define R_PPC_EMB_MRKREF       110
+#define R_PPC_EMB_RELSEC16     111
+#define R_PPC_EMB_RELST_LO     112
+#define R_PPC_EMB_RELST_HI     113
+#define R_PPC_EMB_RELST_HA     114
+#define R_PPC_EMB_BIT_FLD      115
+#define R_PPC_EMB_RELSDA       116     /* 16 bit relative offset in SDA */
+
+/* Diab tool relocations.  */
+#define R_PPC_DIAB_SDA21_LO    180     /* like EMB_SDA21, but lower 16 bit */
+#define R_PPC_DIAB_SDA21_HI    181     /* like EMB_SDA21, but high 16 bit */
+#define R_PPC_DIAB_SDA21_HA    182     /* like EMB_SDA21, adjusted high 16 */
+#define R_PPC_DIAB_RELSDA_LO   183     /* like EMB_RELSDA, but lower 16 bit */
+#define R_PPC_DIAB_RELSDA_HI   184     /* like EMB_RELSDA, but high 16 bit */
+#define R_PPC_DIAB_RELSDA_HA   185     /* like EMB_RELSDA, adjusted high 16 */
+
+/* This is a phony reloc to handle any old fashioned TOC16 references
+   that may still be in object files.  */
+#define R_PPC_TOC16            255
+
+/* PowerPC64 specific values for the Dyn d_tag field.  */
+#define DT_PPC64_GLINK  (DT_LOPROC + 0)
+#define DT_PPC64_NUM    1
+
+/* ARM specific declarations */
+
+/* Processor specific flags for the ELF header e_flags field.  */
+#define EF_ARM_RELEXEC     0x01
+#define EF_ARM_HASENTRY    0x02
+#define EF_ARM_INTERWORK   0x04
+#define EF_ARM_APCS_26     0x08
+#define EF_ARM_APCS_FLOAT  0x10
+#define EF_ARM_PIC         0x20
+#define EF_ARM_ALIGN8      0x40                /* 8-bit structure alignment is in use */
+#define EF_ARM_NEW_ABI     0x80
+#define EF_ARM_OLD_ABI     0x100
+
+/* Other constants defined in the ARM ELF spec. version B-01.  */
+/* NB. These conflict with values defined above.  */
+#define EF_ARM_SYMSARESORTED   0x04
+#define EF_ARM_DYNSYMSUSESEGIDX 0x08
+#define EF_ARM_MAPSYMSFIRST    0x10
+#define EF_ARM_EABIMASK                0XFF000000
+
+#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK)
+#define EF_ARM_EABI_UNKNOWN  0x00000000
+#define EF_ARM_EABI_VER1     0x01000000
+#define EF_ARM_EABI_VER2     0x02000000
+
+/* Additional symbol types for Thumb */
+#define STT_ARM_TFUNC      0xd
+
+/* ARM-specific values for sh_flags */
+#define SHF_ARM_ENTRYSECT  0x10000000   /* Section contains an entry point */
+#define SHF_ARM_COMDEF     0x80000000   /* Section may be multiply defined
+                                          in the input to a link step */
+
+/* ARM-specific program header flags */
+#define PF_ARM_SB          0x10000000   /* Segment contains the location
+                                          addressed by the static base */
+
+/* ARM relocs.  */
+#define R_ARM_NONE             0       /* No reloc */
+#define R_ARM_PC24             1       /* PC relative 26 bit branch */
+#define R_ARM_ABS32            2       /* Direct 32 bit  */
+#define R_ARM_REL32            3       /* PC relative 32 bit */
+#define R_ARM_PC13             4
+#define R_ARM_ABS16            5       /* Direct 16 bit */
+#define R_ARM_ABS12            6       /* Direct 12 bit */
+#define R_ARM_THM_ABS5         7
+#define R_ARM_ABS8             8       /* Direct 8 bit */
+#define R_ARM_SBREL32          9
+#define R_ARM_THM_PC22         10
+#define R_ARM_THM_PC8          11
+#define R_ARM_AMP_VCALL9       12
+#define R_ARM_SWI24            13
+#define R_ARM_THM_SWI8         14
+#define R_ARM_XPC25            15
+#define R_ARM_THM_XPC22                16
+#define R_ARM_COPY             20      /* Copy symbol at runtime */
+#define R_ARM_GLOB_DAT         21      /* Create GOT entry */
+#define R_ARM_JUMP_SLOT                22      /* Create PLT entry */
+#define R_ARM_RELATIVE         23      /* Adjust by program base */
+#define R_ARM_GOTOFF           24      /* 32 bit offset to GOT */
+#define R_ARM_GOTPC            25      /* 32 bit PC relative offset to GOT */
+#define R_ARM_GOT32            26      /* 32 bit GOT entry */
+#define R_ARM_PLT32            27      /* 32 bit PLT address */
+#define R_ARM_ALU_PCREL_7_0    32
+#define R_ARM_ALU_PCREL_15_8   33
+#define R_ARM_ALU_PCREL_23_15  34
+#define R_ARM_LDR_SBREL_11_0   35
+#define R_ARM_ALU_SBREL_19_12  36
+#define R_ARM_ALU_SBREL_27_20  37
+#define R_ARM_GNU_VTENTRY      100
+#define R_ARM_GNU_VTINHERIT    101
+#define R_ARM_THM_PC11         102     /* thumb unconditional branch */
+#define R_ARM_THM_PC9          103     /* thumb conditional branch */
+#define R_ARM_RXPC25           249
+#define R_ARM_RSBREL32         250
+#define R_ARM_THM_RPC22                251
+#define R_ARM_RREL32           252
+#define R_ARM_RABS22           253
+#define R_ARM_RPC24            254
+#define R_ARM_RBASE            255
+/* Keep this the last entry.  */
+#define R_ARM_NUM              256
+
+/* IA-64 specific declarations.  */
+
+/* Processor specific flags for the Ehdr e_flags field.  */
+#define EF_IA_64_MASKOS                0x0000000f      /* os-specific flags */
+#define EF_IA_64_ABI64         0x00000010      /* 64-bit ABI */
+#define EF_IA_64_ARCH          0xff000000      /* arch. version mask */
+
+/* Processor specific values for the Phdr p_type field.  */
+#define PT_IA_64_ARCHEXT       (PT_LOPROC + 0) /* arch extension bits */
+#define PT_IA_64_UNWIND                (PT_LOPROC + 1) /* ia64 unwind bits */
+
+/* Processor specific flags for the Phdr p_flags field.  */
+#define PF_IA_64_NORECOV       0x80000000      /* spec insns w/o recovery */
+
+/* Processor specific values for the Shdr sh_type field.  */
+#define SHT_IA_64_EXT          (SHT_LOPROC + 0) /* extension bits */
+#define SHT_IA_64_UNWIND       (SHT_LOPROC + 1) /* unwind bits */
+
+/* Processor specific flags for the Shdr sh_flags field.  */
+#define SHF_IA_64_SHORT                0x10000000      /* section near gp */
+#define SHF_IA_64_NORECOV      0x20000000      /* spec insns w/o recovery */
+
+/* Processor specific values for the Dyn d_tag field.  */
+#define DT_IA_64_PLT_RESERVE   (DT_LOPROC + 0)
+#define DT_IA_64_NUM           1
+
+/* IA-64 relocations.  */
+#define R_IA64_NONE            0x00    /* none */
+#define R_IA64_IMM14           0x21    /* symbol + addend, add imm14 */
+#define R_IA64_IMM22           0x22    /* symbol + addend, add imm22 */
+#define R_IA64_IMM64           0x23    /* symbol + addend, mov imm64 */
+#define R_IA64_DIR32MSB                0x24    /* symbol + addend, data4 MSB */
+#define R_IA64_DIR32LSB                0x25    /* symbol + addend, data4 LSB */
+#define R_IA64_DIR64MSB                0x26    /* symbol + addend, data8 MSB */
+#define R_IA64_DIR64LSB                0x27    /* symbol + addend, data8 LSB */
+#define R_IA64_GPREL22         0x2a    /* @gprel(sym + add), add imm22 */
+#define R_IA64_GPREL64I                0x2b    /* @gprel(sym + add), mov imm64 */
+#define R_IA64_GPREL32MSB      0x2c    /* @gprel(sym + add), data4 MSB */
+#define R_IA64_GPREL32LSB      0x2d    /* @gprel(sym + add), data4 LSB */
+#define R_IA64_GPREL64MSB      0x2e    /* @gprel(sym + add), data8 MSB */
+#define R_IA64_GPREL64LSB      0x2f    /* @gprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF22         0x32    /* @ltoff(sym + add), add imm22 */
+#define R_IA64_LTOFF64I                0x33    /* @ltoff(sym + add), mov imm64 */
+#define R_IA64_PLTOFF22                0x3a    /* @pltoff(sym + add), add imm22 */
+#define R_IA64_PLTOFF64I       0x3b    /* @pltoff(sym + add), mov imm64 */
+#define R_IA64_PLTOFF64MSB     0x3e    /* @pltoff(sym + add), data8 MSB */
+#define R_IA64_PLTOFF64LSB     0x3f    /* @pltoff(sym + add), data8 LSB */
+#define R_IA64_FPTR64I         0x43    /* @fptr(sym + add), mov imm64 */
+#define R_IA64_FPTR32MSB       0x44    /* @fptr(sym + add), data4 MSB */
+#define R_IA64_FPTR32LSB       0x45    /* @fptr(sym + add), data4 LSB */
+#define R_IA64_FPTR64MSB       0x46    /* @fptr(sym + add), data8 MSB */
+#define R_IA64_FPTR64LSB       0x47    /* @fptr(sym + add), data8 LSB */
+#define R_IA64_PCREL60B                0x48    /* @pcrel(sym + add), brl */
+#define R_IA64_PCREL21B                0x49    /* @pcrel(sym + add), ptb, call */
+#define R_IA64_PCREL21M                0x4a    /* @pcrel(sym + add), chk.s */
+#define R_IA64_PCREL21F                0x4b    /* @pcrel(sym + add), fchkf */
+#define R_IA64_PCREL32MSB      0x4c    /* @pcrel(sym + add), data4 MSB */
+#define R_IA64_PCREL32LSB      0x4d    /* @pcrel(sym + add), data4 LSB */
+#define R_IA64_PCREL64MSB      0x4e    /* @pcrel(sym + add), data8 MSB */
+#define R_IA64_PCREL64LSB      0x4f    /* @pcrel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_FPTR22    0x52    /* @ltoff(@fptr(s+a)), imm22 */
+#define R_IA64_LTOFF_FPTR64I   0x53    /* @ltoff(@fptr(s+a)), imm64 */
+#define R_IA64_LTOFF_FPTR32MSB 0x54    /* @ltoff(@fptr(s+a)), data4 MSB */
+#define R_IA64_LTOFF_FPTR32LSB 0x55    /* @ltoff(@fptr(s+a)), data4 LSB */
+#define R_IA64_LTOFF_FPTR64MSB 0x56    /* @ltoff(@fptr(s+a)), data8 MSB */
+#define R_IA64_LTOFF_FPTR64LSB 0x57    /* @ltoff(@fptr(s+a)), data8 LSB */
+#define R_IA64_SEGREL32MSB     0x5c    /* @segrel(sym + add), data4 MSB */
+#define R_IA64_SEGREL32LSB     0x5d    /* @segrel(sym + add), data4 LSB */
+#define R_IA64_SEGREL64MSB     0x5e    /* @segrel(sym + add), data8 MSB */
+#define R_IA64_SEGREL64LSB     0x5f    /* @segrel(sym + add), data8 LSB */
+#define R_IA64_SECREL32MSB     0x64    /* @secrel(sym + add), data4 MSB */
+#define R_IA64_SECREL32LSB     0x65    /* @secrel(sym + add), data4 LSB */
+#define R_IA64_SECREL64MSB     0x66    /* @secrel(sym + add), data8 MSB */
+#define R_IA64_SECREL64LSB     0x67    /* @secrel(sym + add), data8 LSB */
+#define R_IA64_REL32MSB                0x6c    /* data 4 + REL */
+#define R_IA64_REL32LSB                0x6d    /* data 4 + REL */
+#define R_IA64_REL64MSB                0x6e    /* data 8 + REL */
+#define R_IA64_REL64LSB                0x6f    /* data 8 + REL */
+#define R_IA64_LTV32MSB                0x74    /* symbol + addend, data4 MSB */
+#define R_IA64_LTV32LSB                0x75    /* symbol + addend, data4 LSB */
+#define R_IA64_LTV64MSB                0x76    /* symbol + addend, data8 MSB */
+#define R_IA64_LTV64LSB                0x77    /* symbol + addend, data8 LSB */
+#define R_IA64_PCREL21BI       0x79    /* @pcrel(sym + add), 21bit inst */
+#define R_IA64_PCREL22         0x7a    /* @pcrel(sym + add), 22bit inst */
+#define R_IA64_PCREL64I                0x7b    /* @pcrel(sym + add), 64bit inst */
+#define R_IA64_IPLTMSB         0x80    /* dynamic reloc, imported PLT, MSB */
+#define R_IA64_IPLTLSB         0x81    /* dynamic reloc, imported PLT, LSB */
+#define R_IA64_COPY            0x84    /* copy relocation */
+#define R_IA64_SUB             0x85    /* Addend and symbol difference */
+#define R_IA64_LTOFF22X                0x86    /* LTOFF22, relaxable.  */
+#define R_IA64_LDXMOV          0x87    /* Use of LTOFF22X.  */
+#define R_IA64_TPREL14         0x91    /* @tprel(sym + add), imm14 */
+#define R_IA64_TPREL22         0x92    /* @tprel(sym + add), imm22 */
+#define R_IA64_TPREL64I                0x93    /* @tprel(sym + add), imm64 */
+#define R_IA64_TPREL64MSB      0x96    /* @tprel(sym + add), data8 MSB */
+#define R_IA64_TPREL64LSB      0x97    /* @tprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_TPREL22   0x9a    /* @ltoff(@tprel(s+a)), imm2 */
+#define R_IA64_DTPMOD64MSB     0xa6    /* @dtpmod(sym + add), data8 MSB */
+#define R_IA64_DTPMOD64LSB     0xa7    /* @dtpmod(sym + add), data8 LSB */
+#define R_IA64_LTOFF_DTPMOD22  0xaa    /* @ltoff(@dtpmod(sym + add)), imm22 */
+#define R_IA64_DTPREL14                0xb1    /* @dtprel(sym + add), imm14 */
+#define R_IA64_DTPREL22                0xb2    /* @dtprel(sym + add), imm22 */
+#define R_IA64_DTPREL64I       0xb3    /* @dtprel(sym + add), imm64 */
+#define R_IA64_DTPREL32MSB     0xb4    /* @dtprel(sym + add), data4 MSB */
+#define R_IA64_DTPREL32LSB     0xb5    /* @dtprel(sym + add), data4 LSB */
+#define R_IA64_DTPREL64MSB     0xb6    /* @dtprel(sym + add), data8 MSB */
+#define R_IA64_DTPREL64LSB     0xb7    /* @dtprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_DTPREL22  0xba    /* @ltoff(@dtprel(s+a)), imm22 */
+
+/* SH specific declarations */
+
+/* SH relocs.  */
+#define        R_SH_NONE               0
+#define        R_SH_DIR32              1
+#define        R_SH_REL32              2
+#define        R_SH_DIR8WPN            3
+#define        R_SH_IND12W             4
+#define        R_SH_DIR8WPL            5
+#define        R_SH_DIR8WPZ            6
+#define        R_SH_DIR8BP             7
+#define        R_SH_DIR8W              8
+#define        R_SH_DIR8L              9
+#define        R_SH_SWITCH16           25
+#define        R_SH_SWITCH32           26
+#define        R_SH_USES               27
+#define        R_SH_COUNT              28
+#define        R_SH_ALIGN              29
+#define        R_SH_CODE               30
+#define        R_SH_DATA               31
+#define        R_SH_LABEL              32
+#define        R_SH_SWITCH8            33
+#define        R_SH_GNU_VTINHERIT      34
+#define        R_SH_GNU_VTENTRY        35
+#define        R_SH_TLS_GD_32          144
+#define        R_SH_TLS_LD_32          145
+#define        R_SH_TLS_LDO_32         146
+#define        R_SH_TLS_IE_32          147
+#define        R_SH_TLS_LE_32          148
+#define        R_SH_TLS_DTPMOD32       149
+#define        R_SH_TLS_DTPOFF32       150
+#define        R_SH_TLS_TPOFF32        151
+#define        R_SH_TLS_GD_MOV         152
+#define        R_SH_TLS_LDM_MOV        153
+#define        R_SH_TLS_LDO_MOV        154
+#define        R_SH_TLS_IE_MOV         155
+#define        R_SH_TLS_LE_MOV         156
+#define        R_SH_GOT32              160
+#define        R_SH_PLT32              161
+#define        R_SH_COPY               162
+#define        R_SH_GLOB_DAT           163
+#define        R_SH_JMP_SLOT           164
+#define        R_SH_RELATIVE           165
+#define        R_SH_GOTOFF             166
+#define        R_SH_GOTPC              167
+/* Keep this the last entry.  */
+#define        R_SH_NUM                256
+
+/* Additional s390 relocs */
+
+#define R_390_NONE     0              /* No reloc.  */
+#define R_390_8                1              /* Direct 8 bit.  */
+#define R_390_12       2              /* Direct 12 bit.  */
+#define R_390_16       3              /* Direct 16 bit.  */
+#define R_390_32       4              /* Direct 32 bit.  */
+#define R_390_PC32     5              /* PC relative 32 bit.  */
+#define R_390_GOT12    6              /* 12 bit GOT offset.  */
+#define R_390_GOT32    7              /* 32 bit GOT offset.  */
+#define R_390_PLT32    8              /* 32 bit PC relative PLT address.  */
+#define R_390_COPY     9              /* Copy symbol at runtime.  */
+#define R_390_GLOB_DAT 10             /* Create GOT entry.  */
+#define R_390_JMP_SLOT 11             /* Create PLT entry.  */
+#define R_390_RELATIVE 12             /* Adjust by program base.  */
+#define R_390_GOTOFF   13             /* 32 bit offset to GOT.  */
+#define R_390_GOTPC    14             /* 32 bit PC relative offset to GOT.  */
+#define R_390_GOT16    15             /* 16 bit GOT offset.  */
+#define R_390_PC16     16             /* PC relative 16 bit.  */
+#define R_390_PC16DBL  17             /* PC relative 16 bit shifted by 1.  */
+#define R_390_PLT16DBL 18             /* 16 bit PC rel. PLT shifted by 1.  */
+#define R_390_PC32DBL  19             /* PC relative 32 bit shifted by 1.  */
+#define R_390_PLT32DBL 20             /* 32 bit PC rel. PLT shifted by 1.  */
+#define R_390_GOTPCDBL 21             /* 32 bit PC rel. GOT shifted by 1.  */
+#define R_390_64       22             /* Direct 64 bit.  */
+#define R_390_PC64     23             /* PC relative 64 bit.  */
+#define R_390_GOT64    24             /* 64 bit GOT offset.  */
+#define R_390_PLT64    25             /* 64 bit PC relative PLT address.  */
+#define R_390_GOTENT   26             /* 32 bit PC rel. to GOT entry >> 1. */
+
+/* Keep this the last entry.  */
+#define R_390_NUM      27
+
+/* CRIS relocations.  */
+#define R_CRIS_NONE            0
+#define R_CRIS_8               1
+#define R_CRIS_16              2
+#define R_CRIS_32              3
+#define R_CRIS_8_PCREL         4
+#define R_CRIS_16_PCREL                5
+#define R_CRIS_32_PCREL                6
+#define R_CRIS_GNU_VTINHERIT   7
+#define R_CRIS_GNU_VTENTRY     8
+#define R_CRIS_COPY            9
+#define R_CRIS_GLOB_DAT                10
+#define R_CRIS_JUMP_SLOT       11
+#define R_CRIS_RELATIVE                12
+#define R_CRIS_16_GOT          13
+#define R_CRIS_32_GOT          14
+#define R_CRIS_16_GOTPLT       15
+#define R_CRIS_32_GOTPLT       16
+#define R_CRIS_32_GOTREL       17
+#define R_CRIS_32_PLT_GOTREL   18
+#define R_CRIS_32_PLT_PCREL    19
+
+#define R_CRIS_NUM             20
+
+/* AMD x86-64 relocations.  */
+#define R_X86_64_NONE          0       /* No reloc */
+#define R_X86_64_64            1       /* Direct 64 bit  */
+#define R_X86_64_PC32          2       /* PC relative 32 bit signed */
+#define R_X86_64_GOT32         3       /* 32 bit GOT entry */
+#define R_X86_64_PLT32         4       /* 32 bit PLT address */
+#define R_X86_64_COPY          5       /* Copy symbol at runtime */
+#define R_X86_64_GLOB_DAT      6       /* Create GOT entry */
+#define R_X86_64_JUMP_SLOT     7       /* Create PLT entry */
+#define R_X86_64_RELATIVE      8       /* Adjust by program base */
+#define R_X86_64_GOTPCREL      9       /* 32 bit signed PC relative
+                                          offset to GOT */
+#define R_X86_64_32            10      /* Direct 32 bit zero extended */
+#define R_X86_64_32S           11      /* Direct 32 bit sign extended */
+#define R_X86_64_16            12      /* Direct 16 bit zero extended */
+#define R_X86_64_PC16          13      /* 16 bit sign extended pc relative */
+#define R_X86_64_8             14      /* Direct 8 bit sign extended  */
+#define R_X86_64_PC8           15      /* 8 bit sign extended pc relative */
+#define R_X86_64_DTPMOD64      16      /* ID of module containing symbol */
+#define R_X86_64_DTPOFF64      17      /* Offset in module's TLS block */
+#define R_X86_64_TPOFF64       18      /* Offset in initial TLS block */
+#define R_X86_64_TLSGD         19      /* 32 bit signed PC relative offset
+                                          to two GOT entries for GD symbol */
+#define R_X86_64_TLSLD         20      /* 32 bit signed PC relative offset
+                                          to two GOT entries for LD symbol */
+#define R_X86_64_DTPOFF32      21      /* Offset in TLS block */
+#define r_x86_64_GOTTPOFF      22      /* 32 bit signed PC relative offset
+                                          to GOT entry for IE symbol */
+#define R_X86_64_TPOFF32       23      /* Offset in initial TLS block */
+
+#define R_X86_64_NUM           24
+
+#endif /* ! PUPA_ELF_H */
diff --git a/include/grub/err.h b/include/grub/err.h
new file mode 100644 (file)
index 0000000..4524fc1
--- /dev/null
@@ -0,0 +1,59 @@
+/* err.h - error numbers and prototypes */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_ERR_HEADER
+#define PUPA_ERR_HEADER        1
+
+#include <pupa/symbol.h>
+
+typedef enum
+  {
+    PUPA_ERR_NONE = 0,
+    PUPA_ERR_BAD_MODULE,
+    PUPA_ERR_OUT_OF_MEMORY,
+    PUPA_ERR_BAD_FILE_TYPE,
+    PUPA_ERR_FILE_NOT_FOUND,
+    PUPA_ERR_FILE_READ_ERROR,
+    PUPA_ERR_BAD_FILENAME,
+    PUPA_ERR_UNKNOWN_FS,
+    PUPA_ERR_BAD_FS,
+    PUPA_ERR_BAD_NUMBER,
+    PUPA_ERR_OUT_OF_RANGE,
+    PUPA_ERR_UNKNOWN_DEVICE,
+    PUPA_ERR_BAD_DEVICE,
+    PUPA_ERR_READ_ERROR,
+    PUPA_ERR_WRITE_ERROR,
+    PUPA_ERR_BAD_ARGUMENT,
+    PUPA_ERR_BAD_PART_TABLE,
+    PUPA_ERR_UNKNOWN_OS,
+    PUPA_ERR_BAD_OS,
+    PUPA_ERR_NO_KERNEL,
+    PUPA_ERR_NOT_IMPLEMENTED_YET,
+  }
+pupa_err_t;
+
+extern pupa_err_t EXPORT_VAR(pupa_errno);
+extern char EXPORT_VAR(pupa_errmsg)[];
+
+pupa_err_t EXPORT_FUNC(pupa_error) (pupa_err_t n, const char *fmt, ...);
+void EXPORT_FUNC(pupa_fatal) (const char *fmt, ...) __attribute__ ((noreturn));
+void EXPORT_FUNC(pupa_print_error) (void);
+
+#endif /* ! PUPA_ERR_HEADER */
diff --git a/include/grub/file.h b/include/grub/file.h
new file mode 100644 (file)
index 0000000..5e3a5e6
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_FILE_HEADER
+#define PUPA_FILE_HEADER       1
+
+#include <pupa/types.h>
+#include <pupa/err.h>
+#include <pupa/device.h>
+#include <pupa/fs.h>
+
+/* File description.  */
+struct pupa_file
+{
+  /* The underlying device.  */
+  pupa_device_t device;
+
+  /* The underlying filesystem.  */
+  pupa_fs_t fs;
+
+  /* The current offset.  */
+  pupa_ssize_t offset;
+
+  /* The file size.  */
+  pupa_ssize_t size;
+
+  /* Filesystem-specific data.  */
+  void *data;
+
+  /* This is called when a sector is read. Used only for a disk device.  */
+  void (*read_hook) (unsigned long sector, unsigned offset, unsigned length);
+};
+typedef struct pupa_file *pupa_file_t;
+
+/* Get a device name from NAME.  */
+char *EXPORT_FUNC(pupa_file_get_device_name) (const char *name);
+
+pupa_file_t EXPORT_FUNC(pupa_file_open) (const char *name);
+pupa_ssize_t EXPORT_FUNC(pupa_file_read) (pupa_file_t file, char *buf,
+                                         pupa_ssize_t len);
+pupa_ssize_t EXPORT_FUNC(pupa_file_seek) (pupa_file_t file,
+                                         pupa_ssize_t offset);
+pupa_err_t EXPORT_FUNC(pupa_file_close) (pupa_file_t file);
+
+static inline pupa_ssize_t
+pupa_file_size (const pupa_file_t file)
+{
+  return file->size;
+}
+
+static inline pupa_ssize_t
+pupa_file_tell (const pupa_file_t file)
+{
+  return file->offset;
+}
+
+#endif /* ! PUPA_FILE_HEADER */
diff --git a/include/grub/fs.h b/include/grub/fs.h
new file mode 100644 (file)
index 0000000..079bb68
--- /dev/null
@@ -0,0 +1,63 @@
+/* fs.h - filesystem manager */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_FS_HEADER
+#define PUPA_FS_HEADER 1
+
+#include <pupa/device.h>
+#include <pupa/symbol.h>
+#include <pupa/types.h>
+
+/* Forward declaration is required, because of mutual reference.  */
+struct pupa_file;
+
+/* Filesystem descriptor.  */
+struct pupa_fs
+{
+  /* My name.  */
+  const char *name;
+
+  /* Call HOOK with each file under DIR.  */
+  pupa_err_t (*dir) (pupa_device_t device, const char *path,
+                    int (*hook) (const char *filename, int dir));
+  
+  /* Open a file named NAME and initialize FILE.  */
+  pupa_err_t (*open) (struct pupa_file *file, const char *name);
+  
+  /* Read LEN bytes data from FILE into BUF.  */
+  pupa_ssize_t (*read) (struct pupa_file *file, char *buf, pupa_ssize_t len);
+  
+  /* Close the file FILE.  */
+  pupa_err_t (*close) (struct pupa_file *file);
+
+  /* The next filesystem.  */
+  struct pupa_fs *next;
+};
+typedef struct pupa_fs *pupa_fs_t;
+
+/* This is special, because block lists are not files in usual sense.  */
+extern struct pupa_fs pupa_fs_blocklist;
+
+void EXPORT_FUNC(pupa_fs_register) (pupa_fs_t fs);
+void EXPORT_FUNC(pupa_fs_unregister) (pupa_fs_t fs);
+void EXPORT_FUNC(pupa_fs_iterate) (int (*hook) (const pupa_fs_t fs));
+pupa_fs_t EXPORT_FUNC(pupa_fs_probe) (pupa_device_t device);
+
+#endif /* ! PUPA_FS_HEADER */
diff --git a/include/grub/i386/pc/biosdisk.h b/include/grub/i386/pc/biosdisk.h
new file mode 100644 (file)
index 0000000..0260b96
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_BIOSDISK_MACHINE_HEADER
+#define PUPA_BIOSDISK_MACHINE_HEADER   1
+
+#define PUPA_BIOSDISK_FLAG_LBA 1
+
+struct pupa_biosdisk_data
+{
+  int drive;
+  unsigned long cylinders;
+  unsigned long heads;
+  unsigned long sectors;
+  unsigned long flags;
+};
+
+int pupa_biosdisk_rw_int13_extensions (int ah, int drive, void *dap);
+int pupa_biosdisk_rw_standard (int ah, int drive, int coff, int hoff,
+                              int soff, int nsec, int segment);
+int pupa_biosdisk_check_int13_extensions (int drive);
+int pupa_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp);
+int pupa_biosdisk_get_diskinfo_standard (int drive,
+                                        unsigned long *cylinders,
+                                        unsigned long *heads,
+                                        unsigned long *sectors);
+int pupa_biosdisk_get_num_floppies (void);
+
+void pupa_biosdisk_init (void);
+
+#endif /* ! PUPA_BIOSDISK_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/boot.h b/include/grub/i386/pc/boot.h
new file mode 100644 (file)
index 0000000..b269e72
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 1999, 2000   Free Software Foundation, Inc.
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_BOOT_MACHINE_HEADER
+#define PUPA_BOOT_MACHINE_HEADER       1
+
+/* The signature for bootloader.  */
+#define PUPA_BOOT_MACHINE_SIGNATURE    0xaa55
+
+/* The offset of the end of BPB (BIOS Parameter Block).  */
+#define PUPA_BOOT_MACHINE_BPBEND       0x3e
+
+/* The offset of the major version.  */
+#define PUPA_BOOT_MACHINE_VER_MAJ      0x3e
+
+/* The offset of BOOT_DRIVE.  */
+#define PUPA_BOOT_MACHINE_BOOT_DRIVE   0x40
+
+/* The offset of FORCE_LBA.  */
+#define PUPA_BOOT_MACHINE_FORCE_LBA    0x41
+
+/* The offset of KERNEL_ADDRESS.  */
+#define PUPA_BOOT_MACHINE_KERNEL_ADDRESS       0x42
+
+/* The offset of KERNEL_SECTOR.  */
+#define PUPA_BOOT_MACHINE_KERNEL_SECTOR        0x44
+
+/* The offset of KERNEL_SEGMENT.  */
+#define PUPA_BOOT_MACHINE_KERNEL_SEGMENT       0x48
+
+/* The offset of a magic number used by Windows NT.  */
+#define PUPA_BOOT_MACHINE_WINDOWS_NT_MAGIC     0x1b8
+
+/* The offset of the start of the partition table.  */
+#define PUPA_BOOT_MACHINE_PART_START   0x1be
+
+/* The offset of the end of the partition table.  */
+#define PUPA_BOOT_MACHINE_PART_END     0x1fe
+
+/* The stack segment.  */
+#define PUPA_BOOT_MACHINE_STACK_SEG    0x2000
+
+/* The segment of disk buffer. The disk buffer MUST be 32K long and
+   cannot straddle a 64K boundary.  */
+#define PUPA_BOOT_MACHINE_BUFFER_SEG   0x7000
+
+/* The address of drive parameters.  */
+#define PUPA_BOOT_MACHINE_DRP_ADDR     0x7f00
+
+/* The size of drive parameters.  */
+#define PUPA_BOOT_MACHINE_DRP_SIZE     0x42
+
+/* The flag for BIOS drive number to designate a hard disk vs. a
+   floppy.  */
+#define PUPA_BOOT_MACHINE_BIOS_HD_FLAG 0x80
+
+/* The segment where the kernel is loaded.  */
+#define PUPA_BOOT_MACHINE_KERNEL_SEG   0x800
+
+/* The address where the kernel is loaded.  */
+#define PUPA_BOOT_MACHINE_KERNEL_ADDR  (PUPA_BOOT_MACHINE_KERNEL_SEG << 4)
+
+/* The size of a block list used in the kernel startup code.  */
+#define PUPA_BOOT_MACHINE_LIST_SIZE    8
+
+#endif /* ! BOOT_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/console.h b/include/grub/i386/pc/console.h
new file mode 100644 (file)
index 0000000..69601e5
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_CONSOLE_MACHINE_HEADER
+#define PUPA_CONSOLE_MACHINE_HEADER    1
+
+/* Define scan codes.  */
+#define PUPA_CONSOLE_KEY_LEFT          0x4B00
+#define PUPA_CONSOLE_KEY_RIGHT         0x4D00
+#define PUPA_CONSOLE_KEY_UP            0x4800
+#define PUPA_CONSOLE_KEY_DOWN          0x5000
+#define PUPA_CONSOLE_KEY_IC            0x5200
+#define PUPA_CONSOLE_KEY_DC            0x5300
+#define PUPA_CONSOLE_KEY_BACKSPACE     0x0008
+#define PUPA_CONSOLE_KEY_HOME          0x4700
+#define PUPA_CONSOLE_KEY_END           0x4F00
+#define PUPA_CONSOLE_KEY_NPAGE         0x4900
+#define PUPA_CONSOLE_KEY_PPAGE         0x5100
+
+#ifndef ASM_FILE
+
+#include <pupa/types.h>
+
+/* These are global to share code between C and asm.  */
+extern pupa_uint8_t pupa_console_cur_color;
+void pupa_console_putchar (int c);
+int pupa_console_checkkey (void);
+int pupa_console_getkey (void);
+pupa_uint16_t pupa_console_getxy (void);
+void pupa_console_gotoxy (pupa_uint8_t x, pupa_uint8_t y);
+void pupa_console_cls (void);
+void pupa_console_setcursor (int on);
+
+/* Initialize the console system.  */
+void pupa_console_init (void);
+
+#endif
+
+#endif /* ! PUPA_CONSOLE_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/init.h b/include/grub/i386/pc/init.h
new file mode 100644 (file)
index 0000000..cb91286
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_INIT_MACHINE_HEADER
+#define PUPA_INIT_MACHINE_HEADER       1
+
+#include <pupa/types.h>
+#include <pupa/symbol.h>
+
+/* Get the memory size in KB. If EXTENDED is zero, return conventional
+   memory, otherwise return extended memory.  */
+pupa_uint16_t pupa_get_memsize (int extended);
+
+/* Get a packed EISA memory map. Lower 16 bits are between 1MB and 16MB
+   in 1KB parts, and upper 16 bits are above 16MB in 64KB parts.  */
+pupa_uint32_t pupa_get_eisa_mmap (void);
+
+struct pupa_machine_mmap_entry
+{
+  pupa_uint32_t size;
+  pupa_uint64_t addr;
+  pupa_uint64_t len;
+  pupa_uint32_t type;
+};
+
+/* Get a memory map entry. Return next continuation value. Zero means
+   the end.  */
+pupa_uint32_t pupa_get_mmap_entry (struct pupa_machine_mmap_entry *entry,
+                                  pupa_uint32_t cont);
+
+/* Turn on/off Gate A20.  */
+void EXPORT_FUNC(pupa_gate_a20) (int on);
+
+#endif /* ! PUPA_INIT_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/kernel.h b/include/grub/i386/pc/kernel.h
new file mode 100644 (file)
index 0000000..d6928d3
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef KERNEL_MACHINE_HEADER
+#define KERNEL_MACHINE_HEADER  1
+
+/* The offset of PUPA_TOTAL_MODULE_SIZE.  */
+#define PUPA_KERNEL_MACHINE_TOTAL_MODULE_SIZE  0x8
+
+/* The offset of PUPA_KERNEL_IMAGE_SIZE.  */
+#define PUPA_KERNEL_MACHINE_KERNEL_IMAGE_SIZE  0xc
+
+#endif /* ! KERNEL_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/loader.h b/include/grub/i386/pc/loader.h
new file mode 100644 (file)
index 0000000..d2dcc91
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_LOADER_MACHINE_HEADER
+#define PUPA_LOADER_MACHINE_HEADER     1
+
+#include <pupa/types.h>
+#include <pupa/symbol.h>
+
+/* This is an asm part of the chainloader.  */
+void EXPORT_FUNC(pupa_chainloader_real_boot) (int drive, void *part_addr) __attribute__ ((noreturn));
+
+#endif /* ! PUPA_LOADER_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/memory.h b/include/grub/i386/pc/memory.h
new file mode 100644 (file)
index 0000000..d22f8b6
--- /dev/null
@@ -0,0 +1,67 @@
+/* memory.h - describe the memory map */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_MEMORY_MACHINE_HEADER
+#define PUPA_MEMORY_MACHINE_HEADER     1
+
+/* The scratch buffer used in real mode code.  */
+#define PUPA_MEMORY_MACHINE_SCRATCH_ADDR       0x68000
+#define PUPA_MEMORY_MACHINE_SCRATCH_SEG        (PUPA_MEMORY_MACHINE_SCRATCH_ADDR >> 4)
+#define PUPA_MEMORY_MACHINE_SCRATCH_SIZE       0x10000
+
+/* The real mode stack.  */
+#define PUPA_MEMORY_MACHINE_REAL_STACK (0x2000 - 0x10)
+
+/* The size of the protect mode stack.  */
+#define PUPA_MEMORY_MACHINE_PROT_STACK_SIZE    0x8000
+
+/* The protected mode stack.  */
+#define PUPA_MEMORY_MACHINE_PROT_STACK \
+       (PUPA_MEMORY_MACHINE_SCRATCH_ADDR + PUPA_MEMORY_MACHINE_SCRATCH_SIZE \
+        + PUPA_MEMORY_MACHINE_PROT_STACK_SIZE - 0x10)
+
+/* The memory area where PUPA uses its own purpose.  */
+#define PUPA_MEMORY_MACHINE_RESERVED_START     \
+       PUPA_MEMORY_MACHINE_SCRATCH_ADDR
+#define PUPA_MEMORY_MACHINE_RESERVED_END       \
+       (PUPA_MEMORY_MACHINE_PROT_STACK + 0x10)
+
+/* The address of a partition table passed to another boot loader.  */
+#define PUPA_MEMORY_MACHINE_PART_TABLE_ADDR    0x7be
+
+/* The address where another boot loader is loaded.  */
+#define PUPA_MEMORY_MACHINE_BOOT_LOADER_ADDR   0x7c00
+
+/* The flag for protected mode.  */
+#define PUPA_MEMORY_MACHINE_CR0_PE_ON          0x1
+
+/* The code segment of the protected mode.  */
+#define PUPA_MEMORY_MACHINE_PROT_MODE_CSEG     0x8
+
+/* The data segment of the protected mode.  */
+#define PUPA_MEMORY_MACHINE_PROT_MODE_DSEG     0x10
+
+/* The code segment of the pseudo real mode.  */
+#define PUPA_MEMORY_MACHINE_PSEUDO_REAL_CSEG   0x18
+
+/* The data segment of the pseudo real mode.  */
+#define PUPA_MEMORY_MACHINE_PSEUDO_REAL_DSEG   0x20
+
+#endif /* ! PUPA_MEMORY_MACHINE_HEADER */
diff --git a/include/grub/i386/pc/partition.h b/include/grub/i386/pc/partition.h
new file mode 100644 (file)
index 0000000..10113a4
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 1999,2000,2001  Free Software Foundation, Inc.
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_PARTITION_HEADER
+#define PUPA_PARTITION_HEADER  1
+
+#include <pupa/symbol.h>
+#include <pupa/types.h>
+#include <pupa/err.h>
+
+/* The signature.  */
+#define PUPA_PARTITION_SIGNATURE       0xaa55
+
+/* This is not a flag actually, but used as if it were a flag.  */
+#define PUPA_PARTITION_TYPE_HIDDEN_FLAG                0x10
+
+/* DOS partition types.  */
+#define PUPA_PARTITION_TYPE_NONE               0
+#define PUPA_PARTITION_TYPE_FAT12              1
+#define PUPA_PARTITION_TYPE_FAT16_LT32M                4
+#define PUPA_PARTITION_TYPE_EXTENDED           5
+#define PUPA_PARTITION_TYPE_FAT16_GT32M                6
+#define PUPA_PARTITION_TYPE_FAT32              0xb
+#define PUPA_PARTITION_TYPE_FAT32_LBA          0xc
+#define PUPA_PARTITION_TYPE_FAT16_LBA          0xe
+#define PUPA_PARTITION_TYPE_WIN95_EXTENDED     0xf
+#define PUPA_PARTITION_TYPE_EZD                        0x55
+#define PUPA_PARTITION_TYPE_MINIX              0x80
+#define PUPA_PARTITION_TYPE_LINUX_MINIX                0x81
+#define PUPA_PARTITION_TYPE_EXT2FS             0x83
+#define PUPA_PARTITION_TYPE_LINUX_EXTENDED     0x85
+#define PUPA_PARTITION_TYPE_VSTAFS             0x9e
+#define PUPA_PARTITION_TYPE_FREEBSD            0xa5
+#define PUPA_PARTITION_TYPE_OPENBSD            0xa6
+#define PUPA_PARTITION_TYPE_NETBSD             0xa9
+#define PUPA_PARTITION_TYPE_LINUX_RAID         0xfd
+
+/* Constants for BSD disk label.  */
+#define PUPA_PARTITION_BSD_LABEL_SECTOR                1
+#define PUPA_PARTITION_BSD_LABEL_MAGIC         0x82564557
+#define PUPA_PARTITION_BSD_MAX_ENTRIES         8
+
+/* BSD partition types.  */
+#define PUPA_PARTITION_BSD_TYPE_UNUSED         0
+#define PUPA_PARTITION_BSD_TYPE_SWAP           1
+#define PUPA_PARTITION_BSD_TYPE_V6             2
+#define PUPA_PARTITION_BSD_TYPE_V7             3
+#define PUPA_PARTITION_BSD_TYPE_SYSV           4
+#define PUPA_PARTITION_BSD_TYPE_V71K           5
+#define PUPA_PARTITION_BSD_TYPE_V8             6
+#define PUPA_PARTITION_BSD_TYPE_BSDFFS         7
+#define PUPA_PARTITION_BSD_TYPE_MSDOS          8
+#define PUPA_PARTITION_BSD_TYPE_BSDLFS         9
+#define PUPA_PARTITION_BSD_TYPE_OTHER          10
+#define PUPA_PARTITION_BSD_TYPE_HPFS           11
+#define PUPA_PARTITION_BSD_TYPE_ISO9660                12
+#define PUPA_PARTITION_BSD_TYPE_BOOT           13
+
+/* FreeBSD-specific types.  */
+#define PUPA_PARTITION_FREEBSD_TYPE_VINUM      14
+#define PUPA_PARTITION_FREEBSD_TYPE_RAID       15
+#define PUPA_PARTITION_FREEBSD_TYPE_JFS2       21
+
+/* NetBSD-specific types.  */
+#define        PUPA_PARTITION_NETBSD_TYPE_ADOS         14
+#define        PUPA_PARTITION_NETBSD_TYPE_HFS          15
+#define        PUPA_PARTITION_NETBSD_TYPE_FILECORE     16
+#define        PUPA_PARTITION_NETBSD_TYPE_EXT2FS       17
+#define        PUPA_PARTITION_NETBSD_TYPE_NTFS         18
+#define        PUPA_PARTITION_NETBSD_TYPE_RAID         19
+#define        PUPA_PARTITION_NETBSD_TYPE_CCD          20
+#define        PUPA_PARTITION_NETBSD_TYPE_JFS2         21
+#define        PUPA_PARTITION_NETBSD_TYPE_APPLEUFS     22
+
+/* OpenBSD-specific types.  */
+#define        PUPA_PARTITION_OPENBSD_TYPE_ADOS        14
+#define        PUPA_PARTITION_OPENBSD_TYPE_HFS         15
+#define        PUPA_PARTITION_OPENBSD_TYPE_FILECORE    16
+#define        PUPA_PARTITION_OPENBSD_TYPE_EXT2FS      17
+#define        PUPA_PARTITION_OPENBSD_TYPE_NTFS        18
+#define        PUPA_PARTITION_OPENBSD_TYPE_RAID        19
+
+/* The BSD partition entry.  */
+struct pupa_partition_bsd_entry
+{
+  pupa_uint32_t size;
+  pupa_uint32_t offset;
+  pupa_uint32_t fragment_size;
+  pupa_uint8_t fs_type;
+  pupa_uint8_t fs_fragments;
+  pupa_uint16_t fs_cylinders;
+} __attribute__ ((packed));
+
+/* The BSD disk label. Only define members useful for PUPA.  */
+struct pupa_partition_disk_label
+{
+  pupa_uint32_t magic;
+  pupa_uint8_t padding[128];
+  pupa_uint32_t magic2;
+  pupa_uint16_t checksum;
+  pupa_uint16_t num_partitions;
+  pupa_uint32_t boot_size;
+  pupa_uint32_t superblock_size;
+  struct pupa_partition_bsd_entry entries[PUPA_PARTITION_BSD_MAX_ENTRIES];
+} __attribute__ ((packed));
+
+/* The partition entry.  */
+struct pupa_partition_entry
+{
+  /* If active, 0x80, otherwise, 0x00.  */
+  pupa_uint8_t flag;
+
+  /* The head of the start.  */
+  pupa_uint8_t start_head;
+
+  /* (S | ((C >> 2) & 0xC0)) where S is the sector of the start and C
+     is the cylinder of the start. Note that S is counted from one.  */
+  pupa_uint8_t start_sector;
+
+  /* (C & 0xFF) where C is the cylinder of the start.  */
+  pupa_uint8_t start_cylinder;
+
+  /* The partition type.  */
+  pupa_uint8_t type;
+
+  /* The end versions of start_head, start_sector and start_cylinder,
+     respectively.  */
+  pupa_uint8_t end_head;
+  pupa_uint8_t end_sector;
+  pupa_uint8_t end_cylinder;
+
+  /* The start sector. Note that this is counted from zero.  */
+  pupa_uint32_t start;
+
+  /* The length in sector units.  */
+  pupa_uint32_t length;
+} __attribute__ ((packed));
+
+/* The structure of MBR.  */
+struct pupa_partition_mbr
+{
+  /* The code area (actually, including BPB).  */
+  pupa_uint8_t code[446];
+
+  /* Four partition entries.  */
+  struct pupa_partition_entry entries[4];
+
+  /* The signature 0xaa55.  */
+  pupa_uint16_t signature;
+} __attribute__ ((packed));
+
+/* Partition description.  */
+struct pupa_partition
+{
+  /* The start sector.  */
+  unsigned long start;
+
+  /* The length in sector units.  */
+  unsigned long len;
+
+  /* The offset of the partition table.  */
+  unsigned long offset;
+
+  /* The offset of the extended partition.  */
+  unsigned long ext_offset;
+
+  /* The index of this partition in the partition table.  */
+  int index;
+  
+  /* The DOS partition number.  */
+  int dos_part;
+
+  /* The BSD partition number (a == 0).  */
+  int bsd_part;
+
+  /* The DOS partition type.  */
+  int dos_type;
+
+  /* The BSD partition type.  */
+  int bsd_type;
+};
+typedef struct pupa_partition *pupa_partition_t;
+
+struct pupa_disk;
+
+pupa_partition_t EXPORT_FUNC(pupa_partition_probe) (struct pupa_disk *disk,
+                                                   const char *str);
+pupa_err_t EXPORT_FUNC(pupa_partition_iterate) (struct pupa_disk *disk,
+                                               int (*hook) (const pupa_partition_t partition));
+char *EXPORT_FUNC(pupa_partition_get_name) (const pupa_partition_t partition);
+
+static inline unsigned long
+pupa_partition_get_start (const pupa_partition_t p)
+{
+  return p->start;
+}
+
+static inline unsigned long
+pupa_partition_get_len (const pupa_partition_t p)
+{
+  return p->len;
+}
+
+static inline int
+pupa_partition_is_empty (int type)
+{
+  return (type == PUPA_PARTITION_TYPE_NONE);
+}
+
+static inline int
+pupa_partition_is_extended (int type)
+{
+  return (type == PUPA_PARTITION_TYPE_EXTENDED
+         || type == PUPA_PARTITION_TYPE_WIN95_EXTENDED
+         || type == PUPA_PARTITION_TYPE_LINUX_EXTENDED);
+}
+
+static inline int
+pupa_partition_is_bsd (int type)
+{
+  return (type == PUPA_PARTITION_TYPE_FREEBSD
+         || type == PUPA_PARTITION_TYPE_OPENBSD
+         || type == PUPA_PARTITION_TYPE_NETBSD);
+}
+
+#endif /* ! PUPA_PARTITION_HEADER */
diff --git a/include/grub/i386/types.h b/include/grub/i386/types.h
new file mode 100644 (file)
index 0000000..bc49cd6
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_TYPES_CPU_HEADER
+#define PUPA_TYPES_CPU_HEADER  1
+
+/* The size of void *.  */
+#define PUPA_HOST_SIZEOF_VOID_P        4
+
+/* The size of long.  */
+#define PUPA_HOST_SIZEOF_LONG  4
+
+/* i386 is little-endian.  */
+#undef PUPA_HOST_WORDS_BIGENDIAN
+
+#endif /* ! PUPA_TYPES_CPU_HEADER */
diff --git a/include/grub/kernel.h b/include/grub/kernel.h
new file mode 100644 (file)
index 0000000..4d5a06c
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_KERNEL_HEADER
+#define PUPA_KERNEL_HEADER     1
+
+#include <pupa/types.h>
+
+/* The module header.  */
+struct pupa_module_header
+{
+  /* The offset of object code.  */
+  pupa_off_t offset;
+  /* The size of object code plus this header.  */
+  pupa_size_t size;
+};
+
+/* The start address of the kernel.  */
+extern pupa_addr_t pupa_start_addr;
+
+/* The end address of the kernel.  */
+extern pupa_addr_t pupa_end_addr;
+
+/* The total size of modules including their headers.  */
+extern pupa_size_t pupa_total_module_size;
+
+/* The size of the kernel image.  */
+extern pupa_size_t pupa_kernel_image_size;
+
+/* The start point of the C code.  */
+void pupa_main (void);
+
+/* The machine-specific initialization. This must initialize memory.  */
+void pupa_machine_init (void);
+
+/* Return the end address of the core image.  */
+pupa_addr_t pupa_get_end_addr (void);
+
+/* Register all the exported symbols. This is automatically generated.  */
+void pupa_register_exported_symbols (void);
+
+/* Enter normal mode.  */
+void pupa_enter_normal_mode (void);
+
+#endif /* ! PUPA_KERNEL_HEADER */
diff --git a/include/grub/loader.h b/include/grub/loader.h
new file mode 100644 (file)
index 0000000..ea2d049
--- /dev/null
@@ -0,0 +1,37 @@
+/* loader.h - OS loaders */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_LOADER_HEADER
+#define PUPA_LOADER_HEADER     1
+
+#include <pupa/file.h>
+#include <pupa/symbol.h>
+#include <pupa/err.h>
+#include <pupa/types.h>
+
+void EXPORT_FUNC(pupa_loader_set) (pupa_err_t (*load_module) (int argc,
+                                                             char *argv[]),
+                                  pupa_err_t (*boot) (void),
+                                  pupa_err_t (*unload) (void));
+
+pupa_err_t EXPORT_FUNC(pupa_loader_load_module) (int argc, char *argv[]);
+pupa_err_t EXPORT_FUNC(pupa_loader_boot) (void);
+
+#endif /* ! PUPA_LOADER_HEADER */
diff --git a/include/grub/misc.h b/include/grub/misc.h
new file mode 100644 (file)
index 0000000..fa28322
--- /dev/null
@@ -0,0 +1,47 @@
+/* misc.h - prototypes for misc functions */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_MISC_HEADER
+#define PUPA_MISC_HEADER       1
+
+#include <stdarg.h>
+#include <pupa/types.h>
+#include <pupa/symbol.h>
+
+void *EXPORT_FUNC(pupa_memcpy) (void *dest, const void *src, pupa_size_t n);
+int EXPORT_FUNC(pupa_memcmp) (const void *s1, const void *s2, pupa_size_t n);
+int EXPORT_FUNC(pupa_strcmp) (const char *s1, const char *s2);
+char *EXPORT_FUNC(pupa_strchr) (const char *s, int c);
+char *EXPORT_FUNC(pupa_strrchr) (const char *s, int c);
+int EXPORT_FUNC(pupa_isspace) (int c);
+int EXPORT_FUNC(pupa_isprint) (int c);
+int EXPORT_FUNC(pupa_isalpha) (int c);
+int EXPORT_FUNC(pupa_tolower) (int c);
+unsigned long EXPORT_FUNC(pupa_strtoul) (const char *str, char **end, int base);
+char *EXPORT_FUNC(pupa_strdup) (const char *s);
+void *EXPORT_FUNC(pupa_memset) (void *s, int c, pupa_size_t n);
+pupa_size_t EXPORT_FUNC(pupa_strlen) (const char *s);
+int EXPORT_FUNC(pupa_printf) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+int EXPORT_FUNC(pupa_vprintf) (const char *fmt, va_list args);
+int EXPORT_FUNC(pupa_sprintf) (char *str, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+int EXPORT_FUNC(pupa_vsprintf) (char *str, const char *fmt, va_list args);
+void EXPORT_FUNC(pupa_stop) (void) __attribute__ ((noreturn));
+
+#endif /* ! PUPA_MISC_HEADER */
diff --git a/include/grub/mm.h b/include/grub/mm.h
new file mode 100644 (file)
index 0000000..2033574
--- /dev/null
@@ -0,0 +1,39 @@
+/* mm.h - prototypes and declarations for memory manager */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_MM_H
+#define PUPA_MM_H      1
+
+#include <pupa/types.h>
+#include <pupa/symbol.h>
+
+void pupa_mm_init_region (void *addr, unsigned size);
+void *EXPORT_FUNC(pupa_malloc) (unsigned size);
+void EXPORT_FUNC(pupa_free) (void *ptr);
+void *EXPORT_FUNC(pupa_realloc) (void *ptr, unsigned size);
+void *EXPORT_FUNC(pupa_memalign) (unsigned align, unsigned size);
+
+/* For debugging.  */
+#define MM_DEBUG       1
+#if MM_DEBUG
+void pupa_mm_dump (unsigned lineno);
+#endif
+
+#endif /* ! PUPA_MM_H */
diff --git a/include/grub/net.h b/include/grub/net.h
new file mode 100644 (file)
index 0000000..e7cbcb6
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_NET_HEADER
+#define PUPA_NET_HEADER        1
+
+#include <pupa/symbol.h>
+#include <pupa/err.h>
+#include <pupa/types.h>
+
+struct pupa_net;
+
+struct pupa_net_dev
+{
+  /* The device name.  */
+  const char *name;
+
+  /* FIXME: Just a template.  */
+  int (*probe) (struct pupa_net *net, const void *addr);
+  void (*reset) (struct pupa_net *net);
+  int (*poll) (struct pupa_net *net);
+  void (*transmit) (struct pupa_net *net, const void *destip,
+                   unsigned srcsock, unsigned destsock, const void *packet);
+  void (*disable) (struct pupa_net *net);
+
+  /* The next net device.  */
+  struct pupa_net_dev *next;
+};
+typedef struct pupa_net_dev *pupa_net_dev_t;
+
+struct pupa_fs;
+
+struct pupa_net
+{
+  /* The net name.  */
+  const char *name;
+  
+  /* The underlying disk device.  */
+  pupa_net_dev_t dev;
+
+  /* The binding filesystem.  */
+  struct pupa_fs *fs;
+
+  /* FIXME: More data would be required, such as an IP address, a mask,
+     a gateway, etc.  */
+  
+  /* Device-specific data.  */
+  void *data;
+};
+typedef struct pupa_net *pupa_net_t;
+
+/* FIXME: How to abstract networks? More consideration is necessary.  */
+
+/* Note: Networks are very different from disks, because networks must
+   be initialized before used, and the status is persistent.  */
+
+#endif /* ! PUPA_NET_HEADER */
diff --git a/include/grub/rescue.h b/include/grub/rescue.h
new file mode 100644 (file)
index 0000000..bf10267
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_RESCUE_HEADER
+#define PUPA_RESCUE_HEADER     1
+
+#include <pupa/symbol.h>
+
+/* Enter rescue mode.  */
+void pupa_enter_rescue_mode (void);
+
+/* Register a rescue mode command.  */
+void EXPORT_FUNC(pupa_rescue_register_command) (const char *name,
+                                               void (*func) (int argc,
+                                                             char *argv[]),
+                                               const char *message);
+
+/* Unregister a rescue mode command.  */
+void EXPORT_FUNC(pupa_rescue_unregister_command) (const char *name);
+
+#endif /* ! PUPA_RESCUE_HEADER */
diff --git a/include/grub/symbol.h b/include/grub/symbol.h
new file mode 100644 (file)
index 0000000..c51df26
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 1999,2000,2001,2002  Free Software Foundation, Inc.
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_SYMBOL_HEADER
+#define PUPA_SYMBOL_HEADER     1
+
+#include <config.h>
+
+/* Add an underscore to a C symbol in assembler code if needed. */
+#ifdef HAVE_ASM_USCORE
+# define EXT_C(sym)    _ ## sym
+#else
+# define EXT_C(sym)    sym
+#endif
+
+#define FUNCTION(x)    .globl EXT_C(x) ; EXT_C(x):
+#define VARIABLE(x)    FUNCTION(x)
+
+/* Mark an exported symbol.  */
+#define EXPORT_FUNC(x) x
+#define EXPORT_VAR(x)  x
+
+#endif /* ! PUPA_SYMBOL_HEADER */
diff --git a/include/grub/term.h b/include/grub/term.h
new file mode 100644 (file)
index 0000000..87b285d
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Free Software Foundation, Inc.
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_TERM_HEADER
+#define PUPA_TERM_HEADER       1
+
+#include <pupa/symbol.h>
+#include <pupa/types.h>
+
+/* These are used to represent the various color states we use.  */
+typedef enum
+  {
+    /* The color used to display all text that does not use the
+       user defined colors below.  */
+    PUPA_TERM_COLOR_STANDARD,
+    /* The user defined colors for normal text.  */
+    PUPA_TERM_COLOR_NORMAL,
+    /* The user defined colors for highlighted text.  */
+    PUPA_TERM_COLOR_HIGHLIGHT
+  }
+pupa_term_color_state;
+
+/* Flags for representing the capabilities of a terminal.  */
+/* Some notes about the flags:
+   - These flags are used by higher-level functions but not terminals
+   themselves.
+   - If a terminal is dumb, you may assume that only putchar, getkey and
+   checkkey are called.
+   - Some fancy features (setcolorstate, setcolor and setcursor) can be set
+   to NULL.  */
+
+/* Set when input characters shouldn't be echoed back.  */
+#define PUPA_TERM_NO_ECHO      (1 << 0)
+/* Set when the editing feature should be disabled.  */
+#define PUPA_TERM_NO_EDIT      (1 << 1)
+/* Set when the terminal cannot do fancy things.  */
+#define PUPA_TERM_DUMB         (1 << 2)
+/* Set when the terminal needs to be initialized.  */
+#define PUPA_TERM_NEED_INIT    (1 << 16)
+
+struct pupa_term
+{
+  /* The terminal name.  */
+  const char *name;
+  
+  /* Put a character.  */
+  void (*putchar) (int c);
+  
+  /* Check if any input character is available.  */
+  int (*checkkey) (void);
+  
+  /* Get a character.  */
+  int (*getkey) (void);
+  
+  /* Get the cursor position. The return value is ((X << 8) | Y).  */
+  pupa_uint16_t (*getxy) (void);
+  
+  /* Go to the position (X, Y).  */
+  void (*gotoxy) (pupa_uint8_t x, pupa_uint8_t y);
+  
+  /* Clear the screen.  */
+  void (*cls) (void);
+  
+  /* Set the current color to be used */
+  void (*setcolorstate) (pupa_term_color_state state);
+  
+  /* Set the normal color and the highlight color. The format of each
+     color is VGA's.  */
+  void (*setcolor) (pupa_uint8_t normal_color, pupa_uint8_t highlight_color);
+  
+  /* Turn on/off the cursor.  */
+  void (*setcursor) (int on);
+
+  /* The feature flags defined above.  */
+  pupa_uint32_t flags;
+  
+  /* The next terminal.  */
+  struct pupa_term *next;
+};
+typedef struct pupa_term *pupa_term_t;
+
+void EXPORT_FUNC(pupa_term_register) (pupa_term_t term);
+void EXPORT_FUNC(pupa_term_unregister) (pupa_term_t term);
+void EXPORT_FUNC(pupa_term_iterate) (int (*hook) (pupa_term_t term));
+
+void EXPORT_FUNC(pupa_term_set_current) (pupa_term_t term);
+pupa_term_t EXPORT_FUNC(pupa_term_get_current) (void);
+
+void EXPORT_FUNC(pupa_putchar) (int c);
+int EXPORT_FUNC(pupa_getkey) (void);
+int EXPORT_FUNC(pupa_checkkey) (void);
+pupa_uint16_t EXPORT_FUNC(pupa_getxy) (void);
+void EXPORT_FUNC(pupa_gotoxy) (pupa_uint8_t x, pupa_uint8_t y);
+void EXPORT_FUNC(pupa_cls) (void);
+void EXPORT_FUNC(pupa_setcolorstate) (pupa_term_color_state state);
+void EXPORT_FUNC(pupa_setcolor) (pupa_uint8_t normal_color,
+                                pupa_uint8_t highlight_color);
+int EXPORT_FUNC(pupa_setcursor) (int on);
+
+/* For convenience.  */
+#define PUPA_TERM_ASCII_CHAR(c)        ((c) & 0xff)
+
+#endif /* ! PUPA_TERM_HEADER */
diff --git a/include/grub/types.h b/include/grub/types.h
new file mode 100644 (file)
index 0000000..0dda384
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_TYPES_HEADER
+#define PUPA_TYPES_HEADER      1
+
+#include <config.h>
+#include <pupa/cpu/types.h>
+
+#ifdef PUPA_UTIL
+# define PUPA_CPU_SIZEOF_VOID_P        SIZEOF_VOID_P
+# define PUPA_CPU_SIZEOF_LONG  SIZEOF_LONG
+# ifdef WORDS_BIGENDIAN
+#  define PUPA_CPU_WORDS_BIGENDIAN     1
+# else
+#  undef PUPA_CPU_WORDS_BIGENDIAN
+# endif
+#else /* ! PUPA_UTIL */
+# define PUPA_CPU_SIZEOF_VOID_P        PUPA_HOST_SIZEOF_VOID_P
+# define PUPA_CPU_SIZEOF_LONG  PUPA_HOST_SIZEOF_LONG
+# ifdef PUPA_HOST_WORDS_BIGENDIAN
+#  define PUPA_CPU_WORDS_BIGENDIAN     1
+# else
+#  undef PUPA_CPU_WORDS_BIGENDIAN
+# endif
+#endif /* ! PUPA_UTIL */
+
+#if PUPA_CPU_SIZEOF_VOID_P != PUPA_CPU_SIZEOF_LONG
+# error "This architecture is not supported because sizeof(void *) != sizeof(long)"
+#endif
+
+#if PUPA_CPU_SIZEOF_VOID_P != 4 && PUPA_CPU_SIZEOF_VOID_P != 8
+# error "This architecture is not supported because sizeof(void *) != 4 and sizeof(void *) != 8"
+#endif
+
+/* Define various wide integers.  */
+typedef signed char            pupa_int8_t;
+typedef short                  pupa_int16_t;
+typedef int                    pupa_int32_t;
+#if PUPA_CPU_SIZEOF_VOID_P == 8
+typedef long                   pupa_int64_t;
+#else
+typedef long long              pupa_int64_t;
+#endif
+
+typedef unsigned char          pupa_uint8_t;
+typedef unsigned short         pupa_uint16_t;
+typedef unsigned               pupa_uint32_t;
+#if PUPA_CPU_SIZEOF_VOID_P == 8
+typedef unsigned long          pupa_uint64_t;
+#else
+typedef unsigned long long     pupa_uint64_t;
+#endif
+
+/* Misc types.  */
+#if PUPA_HOST_SIZE_OF_VOID_P == 8
+typedef pupa_uint64_t  pupa_addr_t;
+typedef pupa_uint64_t  pupa_off_t;
+typedef pupa_uint64_t  pupa_size_t;
+typedef pupa_int64_t   pupa_ssize_t;
+#else
+typedef pupa_uint32_t  pupa_addr_t;
+typedef pupa_uint32_t  pupa_off_t;
+typedef pupa_uint32_t  pupa_size_t;
+typedef pupa_int32_t   pupa_ssize_t;
+#endif
+
+/* Byte-orders.  */
+#define pupa_swap_bytes16(x)   \
+({ \
+   pupa_uint16_t _x = (x); \
+   (_x << 8) | (_x >> 8); \
+})
+
+#define pupa_swap_bytes32(x)   \
+({ \
+   pupa_uint32_t _x = (x); \
+   (pupa_uint32_t) ((_x << 24) \
+                    | ((_x & (pupa_uint32_t) 0xFF00UL) << 8) \
+                    | ((_x & (pupa_uint32_t) 0xFF0000UL) >> 8) \
+                    | (_x >> 24)); \
+})
+
+#define pupa_swap_bytes64(x)   \
+({ \
+   pupa_uint64_t _x = (x); \
+   (pupa_uint64_t) ((_x << 56) \
+                    | ((_x & (pupa_uint64_t) 0xFF00ULL) << 40) \
+                    | ((_x & (pupa_uint64_t) 0xFF0000ULL) << 24) \
+                    | ((_x & (pupa_uint64_t) 0xFF000000ULL) << 8) \
+                    | ((_x & (pupa_uint64_t) 0xFF00000000ULL) >> 8) \
+                    | ((_x & (pupa_uint64_t) 0xFF0000000000ULL) >> 24) \
+                    | ((_x & (pupa_uint64_t) 0xFF000000000000ULL) >> 40) \
+                    | (_x >> 56)); \
+})
+
+#ifdef PUPA_CPU_WORDS_BIGENDIAN
+# define pupa_cpu_to_le16(x)   pupa_swap_bytes16(x)
+# define pupa_cpu_to_le32(x)   pupa_swap_bytes32(x)
+# define pupa_cpu_to_le64(x)   pupa_swap_bytes64(x)
+# define pupa_le_to_cpu16(x)   pupa_swap_bytes16(x)
+# define pupa_le_to_cpu32(x)   pupa_swap_bytes32(x)
+# define pupa_le_to_cpu64(x)   pupa_swap_bytes64(x)
+# define pupa_cpu_to_be16(x)   ((pupa_uint16_t) (x))
+# define pupa_cpu_to_be32(x)   ((pupa_uint32_t) (x))
+# define pupa_cpu_to_be64(x)   ((pupa_uint64_t) (x))
+# define pupa_be_to_cpu16(x)   ((pupa_uint16_t) (x))
+# define pupa_be_to_cpu32(x)   ((pupa_uint32_t) (x))
+# define pupa_be_to_cpu64(x)   ((pupa_uint64_t) (x))
+#else /* ! WORDS_BIGENDIAN */
+# define pupa_cpu_to_le16(x)   ((pupa_uint16_t) (x))
+# define pupa_cpu_to_le32(x)   ((pupa_uint32_t) (x))
+# define pupa_cpu_to_le64(x)   ((pupa_uint64_t) (x))
+# define pupa_le_to_cpu16(x)   ((pupa_uint16_t) (x))
+# define pupa_le_to_cpu32(x)   ((pupa_uint32_t) (x))
+# define pupa_le_to_cpu64(x)   ((pupa_uint64_t) (x))
+# define pupa_cpu_to_be16(x)   pupa_swap_bytes16(x)
+# define pupa_cpu_to_be32(x)   pupa_swap_bytes32(x)
+# define pupa_cpu_to_be64(x)   pupa_swap_bytes64(x)
+# define pupa_be_to_cpu16(x)   pupa_swap_bytes16(x)
+# define pupa_be_to_cpu32(x)   pupa_swap_bytes32(x)
+# define pupa_be_to_cpu64(x)   pupa_swap_bytes64(x)
+#endif /* ! WORDS_BIGENDIAN */
+
+#endif /* ! PUPA_TYPES_HEADER */
diff --git a/include/grub/util/misc.h b/include/grub/util/misc.h
new file mode 100644 (file)
index 0000000..48bf0e9
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_UTIL_MISC_HEADER
+#define PUPA_UTIL_MISC_HEADER  1
+
+#include <stdlib.h>
+#include <stdio.h>
+
+extern char *progname;
+extern int verbosity;
+
+void pupa_util_info (const char *fmt, ...);
+void pupa_util_error (const char *fmt, ...) __attribute__ ((noreturn));
+
+void *xmalloc (size_t size);
+char *xstrdup (const char *str);
+
+char *pupa_util_get_path (const char *dir, const char *file);
+size_t pupa_util_get_image_size (const char *path);
+char *pupa_util_read_image (const char *path);
+void pupa_util_write_image (const char *img, size_t size, FILE *out);
+
+#endif /* ! PUPA_UTIL_MISC_HEADER */
diff --git a/include/grub/util/resolve.h b/include/grub/util/resolve.h
new file mode 100644 (file)
index 0000000..35d2507
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef PUPA_UTIL_RESOLVE_HEADER
+#define PUPA_UTIL_RESOLVE_HEADER       1
+
+struct pupa_util_path_list
+{
+  const char *name;
+  struct pupa_util_path_list *next;
+};
+
+/* Resolve the dependencies of the modules MODULES using the information
+   in the file DEP_LIST_FILE. The directory PREFIX is used to find files.  */
+struct pupa_util_path_list *
+pupa_util_resolve_dependencies (const char *prefix,
+                               const char *dep_list_file,
+                               char *modules[]);
+
+#endif /* ! PUPA_UTIL_RESOLVE_HEADER */
diff --git a/install-sh b/install-sh
new file mode 100644 (file)
index 0000000..e9de238
--- /dev/null
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+               chmodcmd=""
+       else
+               instcmd=mkdir
+       fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+       if [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='   
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/kern/device.c b/kern/device.c
new file mode 100644 (file)
index 0000000..2c37d93
--- /dev/null
@@ -0,0 +1,99 @@
+/* device.c - device manager */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/device.h>
+#include <pupa/disk.h>
+#include <pupa/net.h>
+#include <pupa/fs.h>
+#include <pupa/mm.h>
+#include <pupa/misc.h>
+
+static char *pupa_device_root;
+
+pupa_err_t
+pupa_device_set_root (const char *name)
+{
+  pupa_free (pupa_device_root);
+  pupa_device_root = pupa_strdup (name);
+  return pupa_errno;
+}
+
+const char *
+pupa_device_get_root (void)
+{
+  if (! pupa_device_root)
+    pupa_error (PUPA_ERR_BAD_DEVICE, "no root device");
+  
+  return pupa_device_root;
+}
+
+pupa_device_t
+pupa_device_open (const char *name)
+{
+  pupa_disk_t disk = 0;
+  pupa_device_t dev = 0;
+
+  if (! name)
+    {
+      if (! pupa_device_root)
+       {
+         pupa_error (PUPA_ERR_BAD_DEVICE, "no device is set");
+         goto fail;
+       }
+
+      name = pupa_device_root;
+    }
+    
+  dev = pupa_malloc (sizeof (*dev));
+  if (! dev)
+    goto fail;
+  
+  /* Try to open a disk.  */
+  disk = pupa_disk_open (name);
+  if (! disk)
+    {
+      pupa_error (PUPA_ERR_BAD_DEVICE, "unknown device");
+      goto fail;
+    }
+
+  dev->disk = disk;
+  dev->net = 0;        /* FIXME */
+
+  return dev;
+
+ fail:
+  if (disk)
+    pupa_disk_close (disk);
+  
+  pupa_free (dev);
+
+  return 0;
+}
+
+pupa_err_t
+pupa_device_close (pupa_device_t device)
+{
+  if (device->disk)
+    pupa_disk_close (device->disk);
+
+  pupa_free (device);
+
+  return pupa_errno;
+}
diff --git a/kern/disk.c b/kern/disk.c
new file mode 100644 (file)
index 0000000..04e1543
--- /dev/null
@@ -0,0 +1,474 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/disk.h>
+#include <pupa/err.h>
+#include <pupa/mm.h>
+#include <pupa/types.h>
+#include <pupa/machine/partition.h>
+#include <pupa/misc.h>
+
+/* Disk cache.  */
+struct pupa_disk_cache
+{
+  unsigned long id;
+  unsigned long sector;
+  char *data;
+  int lock;
+};
+
+static struct pupa_disk_cache pupa_disk_cache_table[PUPA_DISK_CACHE_NUM];
+
+#if 0
+static unsigned long pupa_disk_cache_hits;
+static unsigned long pupa_disk_cache_misses;
+
+void
+pupa_disk_cache_get_performance (unsigned long *hits, unsigned long *misses)
+{
+  *hits = pupa_disk_cache_hits;
+  *misses = pupa_disk_cache_misses;
+}
+#endif
+
+static unsigned
+pupa_disk_cache_get_index (unsigned long id, unsigned long sector)
+{
+  return ((id * 2606459 + (sector >> PUPA_DISK_CACHE_BITS))
+         % PUPA_DISK_CACHE_NUM);
+}
+
+static void
+pupa_disk_cache_invalidate (unsigned long id, unsigned long sector)
+{
+  unsigned index;
+  struct pupa_disk_cache *cache;
+
+  sector &= ~(PUPA_DISK_CACHE_SIZE - 1);
+  index = pupa_disk_cache_get_index (id, sector);
+  cache = pupa_disk_cache_table + index;
+
+  if (cache->id == id && cache->sector == sector && cache->data)
+    {
+      cache->lock = 1;
+      pupa_free (cache->data);
+      cache->data = 0;
+      cache->lock = 0;
+    }
+}
+
+void
+pupa_disk_cache_invalidate_all (void)
+{
+  unsigned i;
+
+  for (i = 0; i < PUPA_DISK_CACHE_NUM; i++)
+    {
+      struct pupa_disk_cache *cache = pupa_disk_cache_table + i;
+
+      if (cache->data && ! cache->lock)
+       {
+         pupa_free (cache->data);
+         cache->data = 0;
+       }
+    }
+}
+
+static char *
+pupa_disk_cache_fetch (unsigned long id, unsigned long sector)
+{
+  struct pupa_disk_cache *cache;
+  unsigned index;
+
+  index = pupa_disk_cache_get_index (id, sector);
+  cache = pupa_disk_cache_table + index;
+
+  if (cache->id == id && cache->sector == sector)
+    {
+      cache->lock = 1;
+#if 0
+      pupa_disk_cache_hits++;
+#endif
+      return cache->data;
+    }
+
+#if 0
+  pupa_disk_cache_misses++;
+#endif
+  
+  return 0;
+}
+
+static void
+pupa_disk_cache_unlock (unsigned long id, unsigned long sector)
+{
+  struct pupa_disk_cache *cache;
+  unsigned index;
+
+  index = pupa_disk_cache_get_index (id, sector);
+  cache = pupa_disk_cache_table + index;
+
+  if (cache->id == id && cache->sector == sector)
+    cache->lock = 0;
+}
+
+static pupa_err_t
+pupa_disk_cache_store (unsigned long id, unsigned long sector,
+                      const char *data)
+{
+  unsigned index;
+  struct pupa_disk_cache *cache;
+  
+  pupa_disk_cache_invalidate (id, sector);
+  
+  index = pupa_disk_cache_get_index (id, sector);
+  cache = pupa_disk_cache_table + index;
+  
+  cache->data = pupa_malloc (PUPA_DISK_SECTOR_SIZE << PUPA_DISK_CACHE_BITS);
+  if (! cache->data)
+    return pupa_errno;
+  
+  pupa_memcpy (cache->data, data,
+              PUPA_DISK_SECTOR_SIZE << PUPA_DISK_CACHE_BITS);
+  cache->id = id;
+  cache->sector = sector;
+
+  return PUPA_ERR_NONE;
+}
+
+\f
+
+static pupa_disk_dev_t pupa_disk_dev_list;
+
+void
+pupa_disk_dev_register (pupa_disk_dev_t dev)
+{
+  dev->next = pupa_disk_dev_list;
+  pupa_disk_dev_list = dev;
+}
+
+void
+pupa_disk_dev_unregister (pupa_disk_dev_t dev)
+{
+  pupa_disk_dev_t *p, q;
+  
+  for (p = &pupa_disk_dev_list, q = *p; q; p = &(q->next), q = q->next)
+    if (q == dev)
+      {
+        *p = q->next;
+       break;
+      }
+}
+
+void
+pupa_disk_dev_iterate (int (*hook) (const char *name))
+{
+  pupa_disk_dev_t p;
+
+  for (p = pupa_disk_dev_list; p; p = p->next)
+    if ((p->iterate) (hook))
+      break;
+}
+
+pupa_disk_t
+pupa_disk_open (const char *name)
+{
+  char *p;
+  pupa_disk_t disk;
+  pupa_disk_dev_t dev;
+  char *raw = (char *) name;
+  
+  disk = (pupa_disk_t) pupa_malloc (sizeof (*disk));
+  if (! disk)
+    return 0;
+
+  disk->dev = 0;
+  disk->read_hook = 0;
+  disk->partition = 0;
+  disk->data = 0;
+  disk->name = pupa_strdup (name);
+  if (! disk->name)
+    goto fail;
+  
+  p = pupa_strchr (name, ',');
+  if (p)
+    {
+      pupa_size_t len = p - name;
+      
+      raw = pupa_malloc (len + 1);
+      if (! raw)
+       goto fail;
+
+      pupa_memcpy (raw, name, len);
+      raw[len] = '\0';
+    }
+
+  for (dev = pupa_disk_dev_list; dev; dev = dev->next)
+    {
+      if ((dev->open) (raw, disk) == PUPA_ERR_NONE)
+       break;
+      else if (pupa_errno == PUPA_ERR_UNKNOWN_DEVICE)
+       pupa_errno = PUPA_ERR_NONE;
+      else
+       goto fail;
+    }
+
+  if (! dev)
+    {
+      pupa_error (PUPA_ERR_UNKNOWN_DEVICE, "no such disk");
+      goto fail;
+    }
+
+  if (p && ! disk->has_partitions)
+    {
+      pupa_error (PUPA_ERR_BAD_DEVICE, "no partition on this disk");
+      goto fail;
+    }
+  
+  disk->dev = dev;
+
+  if (p)
+    disk->partition = pupa_partition_probe (disk, p + 1);
+
+ fail:
+  
+  if (raw && raw != name)
+    pupa_free (raw);
+
+  if (pupa_errno != PUPA_ERR_NONE)
+    {
+      pupa_disk_close (disk);
+      return 0;
+    }
+
+  return disk;
+}
+
+void
+pupa_disk_close (pupa_disk_t disk)
+{
+  if (disk->dev && disk->dev->close)
+    (disk->dev->close) (disk);
+
+  pupa_free (disk->partition);
+  pupa_free ((void *) disk->name);
+  pupa_free (disk);
+}
+
+static pupa_err_t
+pupa_disk_check_range (pupa_disk_t disk, unsigned long *sector,
+                      unsigned long *offset, pupa_ssize_t size)
+{
+  *sector += *offset >> PUPA_DISK_SECTOR_BITS;
+  *offset &= PUPA_DISK_SECTOR_SIZE - 1;
+  
+  if (disk->partition)
+    {
+      unsigned long start, len;
+
+      start = pupa_partition_get_start (disk->partition);
+      len = pupa_partition_get_len (disk->partition);
+
+      if (*sector >= len
+         || len - *sector < ((*offset + size + PUPA_DISK_SECTOR_SIZE - 1)
+                             >> PUPA_DISK_SECTOR_BITS))
+       return pupa_error (PUPA_ERR_OUT_OF_RANGE, "out of partition");
+
+      *sector += start;
+    }
+
+  if (disk->total_sectors <= *sector
+      || ((*offset + size + PUPA_DISK_SECTOR_SIZE - 1)
+         >> PUPA_DISK_SECTOR_BITS) > disk->total_sectors - *sector)
+    return pupa_error (PUPA_ERR_OUT_OF_RANGE, "out of disk");
+
+  return PUPA_ERR_NONE;
+}
+
+/* Read data from the disk.  */
+pupa_err_t
+pupa_disk_read (pupa_disk_t disk, unsigned long sector,
+               unsigned long offset, unsigned long size, char *buf)
+{
+  char *tmp_buf;
+
+  /* First of all, check if the region is within the disk.  */
+  if (pupa_disk_check_range (disk, &sector, &offset, size) != PUPA_ERR_NONE)
+    return pupa_errno;
+
+  /* Allocate a temporary buffer.  */
+  tmp_buf = pupa_malloc (PUPA_DISK_SECTOR_SIZE << PUPA_DISK_CACHE_BITS);
+  if (! tmp_buf)
+    return pupa_errno;
+
+  /* Until SIZE is zero...  */
+  while (size)
+    {
+      char *data;
+      unsigned long start_sector;
+      unsigned long len;
+      unsigned long pos;
+
+      /* For reading bulk data.  */
+      start_sector = sector & ~(PUPA_DISK_CACHE_SIZE - 1);
+      pos = (sector - start_sector) << PUPA_DISK_SECTOR_BITS;
+      len = (PUPA_DISK_SECTOR_SIZE << PUPA_DISK_CACHE_BITS) - pos - offset;
+      if (len > size)
+       len = size;
+
+      /* Fetch the cache.  */
+      data = pupa_disk_cache_fetch (disk->id, start_sector);
+      if (data)
+       {
+         /* Just copy it!  */
+         pupa_memcpy (buf, data + pos + offset, len);
+         pupa_disk_cache_unlock (disk->id, start_sector);
+       }
+      else
+       {
+         /* Otherwise read data from the disk actually.  */
+         if ((disk->dev->read) (disk, start_sector,
+                                PUPA_DISK_CACHE_SIZE, tmp_buf)
+             != PUPA_ERR_NONE)
+           {
+             /* Uggh... Failed. Instead, just read necessary data.  */
+             unsigned num;
+
+             /* If more data is required, no way.  */
+             if (pos + size
+                 >= (PUPA_DISK_SECTOR_SIZE << PUPA_DISK_CACHE_BITS))
+               goto finish;
+
+             num = ((size + PUPA_DISK_SECTOR_SIZE - 1)
+                    >> PUPA_DISK_SECTOR_BITS);
+             if ((disk->dev->read) (disk, sector, num, tmp_buf))
+               goto finish;
+
+             pupa_memcpy (buf, tmp_buf + offset, size);
+
+             /* Call the read hook, if any.  */
+             if (disk->read_hook)
+               while (size)
+                 {
+                   (disk->read_hook) (sector, offset,
+                                      ((size > PUPA_DISK_SECTOR_SIZE)
+                                       ? PUPA_DISK_SECTOR_SIZE
+                                       : size));
+                   sector++;
+                   size -= PUPA_DISK_SECTOR_SIZE - offset;
+                   offset = 0;
+                 }
+
+             /* This must be the end.  */
+             goto finish;
+           }
+
+         /* Copy it and store it in the disk cache.  */
+         pupa_memcpy (buf, tmp_buf + pos + offset, len);
+         pupa_disk_cache_store (disk->id, start_sector, tmp_buf);
+       }
+
+      /* Call the read hook, if any.  */
+      if (disk->read_hook)
+       {
+         unsigned long s = sector;
+         unsigned long l = len;
+         
+         while (l)
+           {
+             (disk->read_hook) (s, offset,
+                                ((l > PUPA_DISK_SECTOR_SIZE)
+                                 ? PUPA_DISK_SECTOR_SIZE
+                                 : l));
+             s++;
+             l -= PUPA_DISK_SECTOR_SIZE - offset;
+             offset = 0;
+           }
+       }
+      
+      sector = start_sector + PUPA_DISK_CACHE_SIZE;
+      buf += len;
+      size -= len;
+      offset = 0;
+    }
+  
+ finish:
+  
+  pupa_free (tmp_buf);
+  
+  return pupa_errno;
+}
+
+pupa_err_t
+pupa_disk_write (pupa_disk_t disk, unsigned long sector,
+                unsigned long offset, unsigned long size, const char *buf)
+{
+  if (pupa_disk_check_range (disk, &sector, &offset, size) != PUPA_ERR_NONE)
+    return -1;
+
+  while (size)
+    {
+      if (offset != 0 || (size < PUPA_DISK_SECTOR_SIZE && size != 0))
+       {
+         char tmp_buf[PUPA_DISK_SECTOR_SIZE];
+         unsigned long len;
+         
+         if (pupa_disk_read (disk, sector, 0, PUPA_DISK_SECTOR_SIZE, tmp_buf)
+             != PUPA_ERR_NONE)
+           goto finish;
+
+         len = PUPA_DISK_SECTOR_SIZE - offset;
+         if (len > size)
+           len = size;
+         
+         pupa_memcpy (tmp_buf + offset, buf, len);
+
+         pupa_disk_cache_invalidate (disk->id, sector);
+
+         if ((disk->dev->write) (disk, sector, 1, tmp_buf) != PUPA_ERR_NONE)
+           goto finish;
+
+         sector++;
+         buf += len;
+         size -= len;
+         offset = 0;
+       }
+      else
+       {
+         unsigned long len;
+         unsigned long n;
+
+         len = size & ~(PUPA_DISK_SECTOR_SIZE - 1);
+         n = size >> PUPA_DISK_SECTOR_BITS;
+         
+         if ((disk->dev->write) (disk, sector, n, buf) != PUPA_ERR_NONE)
+           goto finish;
+
+         while (n--)
+           pupa_disk_cache_invalidate (disk->id, sector++);
+
+         buf += len;
+         size -= len;
+       }
+    }
+
+ finish:
+
+  return pupa_errno;
+}
diff --git a/kern/dl.c b/kern/dl.c
new file mode 100644 (file)
index 0000000..c22c984
--- /dev/null
+++ b/kern/dl.c
@@ -0,0 +1,599 @@
+/* dl.c - loadable module support */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+#include <pupa/elf.h>
+#include <pupa/dl.h>
+#include <pupa/misc.h>
+#include <pupa/mm.h>
+#include <pupa/err.h>
+#include <pupa/types.h>
+#include <pupa/symbol.h>
+#include <pupa/file.h>
+
+#if PUPA_HOST_SIZEOF_VOID_P == 4
+
+typedef Elf32_Word Elf_Word;
+typedef Elf32_Addr Elf_Addr;
+typedef Elf32_Ehdr Elf_Ehdr;
+typedef Elf32_Shdr Elf_Shdr;
+typedef Elf32_Sym Elf_Sym;
+
+# define ELF_ST_BIND(val)      ELF32_ST_BIND (val)
+# define ELF_ST_TYPE(val)      ELF32_ST_TYPE (val)
+
+#elif PUPA_HOST_SIZEOF_VOID_P == 8
+
+typedef Elf64_Word Elf_Word;
+typedef Elf64_Addr Elf_Addr;
+typedef Elf64_Ehdr Elf_Ehdr;
+typedef Elf64_Shdr Elf_Shdr;
+typedef Elf64_Sym Elf_Sym;
+
+# define ELF_ST_BIND(val)      ELF64_ST_BIND (val)
+# define ELF_ST_TYPE(val)      ELF64_ST_TYPE (val)
+
+#endif
+
+\f
+
+struct pupa_dl_list
+{
+  struct pupa_dl_list *next;
+  pupa_dl_t mod;
+};
+typedef struct pupa_dl_list *pupa_dl_list_t;
+
+static pupa_dl_list_t pupa_dl_head;
+
+static pupa_err_t
+pupa_dl_add (pupa_dl_t mod)
+{
+  pupa_dl_list_t l;
+
+  if (pupa_dl_get (mod->name))
+    return pupa_error (PUPA_ERR_BAD_MODULE,
+                      "`%s' is already loaded", mod->name);
+  
+  l = (pupa_dl_list_t) pupa_malloc (sizeof (*l));
+  if (! l)
+    return pupa_errno;
+
+  l->mod = mod;
+  l->next = pupa_dl_head;
+  pupa_dl_head = l;
+
+  return PUPA_ERR_NONE;
+}
+
+static void
+pupa_dl_remove (pupa_dl_t mod)
+{
+  pupa_dl_list_t *p, q;
+
+  for (p = &pupa_dl_head, q = *p; q; p = &q->next, q = *p)
+    if (q->mod == mod)
+      {
+       *p = q->next;
+       pupa_free (q);
+       return;
+      }
+}
+
+pupa_dl_t
+pupa_dl_get (const char *name)
+{
+  pupa_dl_list_t l;
+
+  for (l = pupa_dl_head; l; l = l->next)
+    if (pupa_strcmp (name, l->mod->name) == 0)
+      return l->mod;
+
+  return 0;
+}
+
+\f
+
+struct pupa_symbol
+{
+  struct pupa_symbol *next;
+  const char *name;
+  void *addr;
+  pupa_dl_t mod;       /* The module to which this symbol belongs.  */
+};
+typedef struct pupa_symbol *pupa_symbol_t;
+
+/* The size of the symbol table.  */
+#define PUPA_SYMTAB_SIZE       509
+
+/* The symbol table (using an open-hash).  */
+static struct pupa_symbol *pupa_symtab[PUPA_SYMTAB_SIZE];
+
+/* Simple hash function.  */
+static unsigned
+pupa_symbol_hash (const char *s)
+{
+  unsigned key = 0;
+
+  while (*s)
+    key = key * 65599 + *s++;
+
+  return (key + (key >> 5)) % PUPA_SYMTAB_SIZE;
+}
+
+/* Resolve the symbol name NAME and return the address.
+   Return NULL, if not found.  */
+void *
+pupa_dl_resolve_symbol (const char *name)
+{
+  pupa_symbol_t sym;
+
+  for (sym = pupa_symtab[pupa_symbol_hash (name)]; sym; sym = sym->next)
+    if (pupa_strcmp (sym->name, name) == 0)
+      return sym->addr;
+
+  return 0;
+}
+
+/* Register a symbol with the name NAME and the address ADDR.  */
+pupa_err_t
+pupa_dl_register_symbol (const char *name, void *addr, pupa_dl_t mod)
+{
+  pupa_symbol_t sym;
+  unsigned k;
+  
+  sym = (pupa_symbol_t) pupa_malloc (sizeof (*sym));
+  if (! sym)
+    return pupa_errno;
+
+  if (mod)
+    {
+      sym->name = pupa_strdup (name);
+      if (! sym->name)
+       {
+         pupa_free (sym);
+         return pupa_errno;
+       }
+    }
+  else
+    sym->name = name;
+  
+  sym->addr = addr;
+  sym->mod = mod;
+  
+  k = pupa_symbol_hash (name);
+  sym->next = pupa_symtab[k];
+  pupa_symtab[k] = sym;
+
+  return PUPA_ERR_NONE;
+}
+
+/* Unregister all the symbols defined in the module MOD.  */
+static void
+pupa_dl_unregister_symbols (pupa_dl_t mod)
+{
+  unsigned i;
+
+  if (! mod)
+    pupa_fatal ("core symbols cannot be unregistered");
+  
+  for (i = 0; i < PUPA_SYMTAB_SIZE; i++)
+    {
+      pupa_symbol_t sym, *p, q;
+
+      for (p = &pupa_symtab[i], sym = *p; sym; sym = q)
+       {
+         q = sym->next;
+         if (sym->mod == mod)
+           {
+             *p = q;
+             pupa_free ((void *) sym->name);
+             pupa_free (sym);
+           }
+         else
+           p = &sym->next;
+       }
+    }
+}
+
+/* Return the address of a section whose index is N.  */
+static void *
+pupa_dl_get_section_addr (pupa_dl_t mod, unsigned n)
+{
+  pupa_dl_segment_t seg;
+
+  for (seg = mod->segment; seg; seg = seg->next)
+    if (seg->section == n)
+      return seg->addr;
+
+  return 0;
+}
+
+/* Load all segments from memory specified by E.  */
+static pupa_err_t
+pupa_dl_load_segments (pupa_dl_t mod, const Elf_Ehdr *e)
+{
+  unsigned i;
+  Elf_Shdr *s;
+  
+  for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize))
+    {
+      if (s->sh_flags & SHF_ALLOC)
+       {
+         pupa_dl_segment_t seg;
+
+         seg = (pupa_dl_segment_t) pupa_malloc (sizeof (*seg));
+         if (! seg)
+           return pupa_errno;
+         
+         if (s->sh_size)
+           {
+             void *addr;
+
+             addr = pupa_memalign (s->sh_addralign, s->sh_size);
+             if (! addr)
+               {
+                 pupa_free (seg);
+                 return pupa_errno;
+               }
+
+             switch (s->sh_type)
+               {
+               case SHT_PROGBITS:
+                 pupa_memcpy (addr, (char *) e + s->sh_offset, s->sh_size);
+                 break;
+               case SHT_NOBITS:
+                 pupa_memset (addr, 0, s->sh_size);
+                 break;
+               }
+
+             seg->addr = addr;
+           }
+         else
+           seg->addr = 0;
+
+         seg->size = s->sh_size;
+         seg->section = i;
+         seg->next = mod->segment;
+         mod->segment = seg;
+       }
+    }
+
+  return PUPA_ERR_NONE;
+}
+
+static pupa_err_t
+pupa_dl_resolve_symbols (pupa_dl_t mod, Elf_Ehdr *e)
+{
+  unsigned i;
+  Elf_Shdr *s;
+  Elf_Sym *sym;
+  const char *str;
+  Elf_Word size, entsize;
+  
+  for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
+    if (s->sh_type == SHT_SYMTAB)
+      break;
+
+  if (i == e->e_shnum)
+    return pupa_error (PUPA_ERR_BAD_MODULE, "no symbol table");
+
+  sym = (Elf_Sym *) ((char *) e + s->sh_offset);
+  size = s->sh_size;
+  entsize = s->sh_entsize;
+  
+  s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shentsize * s->sh_link);
+  str = (char *) e + s->sh_offset;
+
+  for (i = 0;
+       i < size / entsize;
+       i++, sym = (Elf_Sym *) ((char *) sym + entsize))
+    {
+      unsigned char type = ELF_ST_TYPE (sym->st_info);
+      unsigned char bind = ELF_ST_BIND (sym->st_info);
+      const char *name = str + sym->st_name;
+      
+      switch (type)
+       {
+       case STT_NOTYPE:
+         /* Resolve a global symbol.  */
+         if (sym->st_name != 0 && sym->st_shndx == 0)
+           {
+             sym->st_value = (Elf_Addr) pupa_dl_resolve_symbol (name);
+             if (! sym->st_value)
+               return pupa_error (PUPA_ERR_BAD_MODULE,
+                                  "the symbol `%s' not found", name);
+           }
+         else
+           sym->st_value = 0;
+         break;
+
+       case STT_OBJECT:
+         sym->st_value += (Elf_Addr) pupa_dl_get_section_addr (mod,
+                                                               sym->st_shndx);
+         if (bind != STB_LOCAL)
+           if (pupa_dl_register_symbol (name, (void *) sym->st_value, mod))
+             return pupa_errno;
+         break;
+
+       case STT_FUNC:
+         sym->st_value += (Elf_Addr) pupa_dl_get_section_addr (mod,
+                                                               sym->st_shndx);
+         if (bind != STB_LOCAL)
+           if (pupa_dl_register_symbol (name, (void *) sym->st_value, mod))
+             return pupa_errno;
+         
+         if (pupa_strcmp (name, "pupa_mod_init") == 0)
+           mod->init = (void (*) ()) sym->st_value;
+         else if (pupa_strcmp (name, "pupa_mod_fini") == 0)
+           mod->fini = (void (*) ()) sym->st_value;
+         break;
+
+       case STT_SECTION:
+         sym->st_value = (Elf_Addr) pupa_dl_get_section_addr (mod,
+                                                              sym->st_shndx);
+         break;
+
+       case STT_FILE:
+         sym->st_value = 0;
+         break;
+
+       default:
+         return pupa_error (PUPA_ERR_BAD_MODULE,
+                            "unknown symbol type `%d'", (int) type);
+       }
+    }
+
+  return PUPA_ERR_NONE;
+}
+
+static void
+pupa_dl_call_init (pupa_dl_t mod)
+{
+  if (mod->init)
+    (mod->init) ();
+}
+
+static pupa_err_t
+pupa_dl_resolve_name (pupa_dl_t mod, Elf_Ehdr *e)
+{
+  Elf_Shdr *s;
+  const char *str;
+  unsigned i;
+
+  s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize);
+  str = (char *) e + s->sh_offset;
+
+  for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
+    if (pupa_strcmp (str + s->sh_name, ".modname") == 0)
+      {
+       mod->name = pupa_strdup ((char *) e + s->sh_offset);
+       if (! mod->name)
+         return pupa_errno;
+       break;
+      }
+
+  if (i == e->e_shnum)
+    return pupa_error (PUPA_ERR_BAD_MODULE, "no module name found");
+
+  return PUPA_ERR_NONE;
+}
+
+static pupa_err_t
+pupa_dl_resolve_dependencies (pupa_dl_t mod, Elf_Ehdr *e)
+{
+  Elf_Shdr *s;
+  const char *str;
+  unsigned i;
+
+  s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize);
+  str = (char *) e + s->sh_offset;
+  
+  for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
+    if (pupa_strcmp (str + s->sh_name, ".moddeps") == 0)
+      {
+       const char *name = (char *) e + s->sh_offset;
+       const char *max = name + s->sh_size;
+
+       while (name < max)
+         {
+           pupa_dl_t m;
+           pupa_dl_dep_t dep;
+           
+           m = pupa_dl_load (name);
+           if (! m)
+             return pupa_errno;
+           
+           dep = (pupa_dl_dep_t) pupa_malloc (sizeof (*dep));
+           if (! dep)
+             return pupa_errno;
+           
+           dep->mod = m;
+           dep->next = mod->dep;
+           mod->dep = dep;
+           
+           name += pupa_strlen (name) + 1;
+         }
+      }
+
+  return PUPA_ERR_NONE;
+}
+
+/* Load a module from core memory.  */
+pupa_dl_t
+pupa_dl_load_core (void *addr, pupa_size_t size)
+{
+  Elf_Ehdr *e;
+  pupa_dl_t mod;
+  
+  e = addr;
+  if (! pupa_arch_dl_check_header (e, size))
+    {
+      pupa_error (PUPA_ERR_BAD_MODULE, "invalid ELF header");
+      return 0;
+    }
+  
+  mod = (pupa_dl_t) pupa_malloc (sizeof (*mod));
+  if (! mod)
+    return 0;
+
+  mod->name = 0;
+  mod->ref_count = 1;
+  mod->dep = 0;
+  mod->segment = 0;
+  mod->init = 0;
+  mod->fini = 0;
+
+  if (pupa_dl_resolve_name (mod, e)
+      || pupa_dl_resolve_dependencies (mod, e)
+      || pupa_dl_load_segments (mod, e)
+      || pupa_dl_resolve_symbols (mod, e)
+      || pupa_arch_dl_relocate_symbols (mod, e))
+    {
+      mod->fini = 0;
+      pupa_dl_unload (mod);
+      return 0;
+    }
+
+  pupa_dl_call_init (mod);
+  
+  if (pupa_dl_add (mod))
+    {
+      pupa_dl_unload (mod);
+      return 0;
+    }
+  
+  return mod;
+}
+
+/* Load a module from the file FILENAME.  */
+pupa_dl_t
+pupa_dl_load_file (const char *filename)
+{
+  pupa_file_t file;
+  pupa_ssize_t size;
+  void *core = 0;
+  pupa_dl_t mod = 0;
+  
+  file = pupa_file_open (filename);
+  if (! file)
+    return 0;
+
+  size = pupa_file_size (file);
+  core = pupa_malloc (size);
+  if (! core)
+    goto failed;
+
+  if (pupa_file_read (file, core, size) != (int) size)
+    goto failed;
+
+  mod = pupa_dl_load_core (core, size);
+
+ failed:
+  pupa_file_close (file);
+  pupa_free (core);
+
+  return mod;
+}
+
+static char *pupa_dl_dir;
+
+/* Load a module using a symbolic name.  */
+pupa_dl_t
+pupa_dl_load (const char *name)
+{
+  char *filename;
+  pupa_dl_t mod;
+
+  mod = pupa_dl_get (name);
+  if (mod)
+    {
+      mod->ref_count++;
+      return mod;
+    }
+  
+  if (! pupa_dl_dir)
+    pupa_fatal ("module dir is not initialized yet");
+
+  filename = (char *) pupa_malloc (pupa_strlen (pupa_dl_dir) + 1
+                                  + pupa_strlen (name) + 3);
+  if (! filename)
+    return 0;
+  
+  pupa_sprintf (filename, "%s/%s.o", pupa_dl_dir, name);
+  mod = pupa_dl_load_file (filename);
+  pupa_free (filename);
+
+  if (! mod)
+    return 0;
+  
+  if (pupa_strcmp (mod->name, name) != 0)
+    pupa_error (PUPA_ERR_BAD_MODULE, "mismatched names");
+  
+  return mod;
+}
+
+/* Unload the module MOD.  */
+void
+pupa_dl_unload (pupa_dl_t mod)
+{
+  pupa_dl_dep_t dep, depn;
+  pupa_dl_segment_t seg, segn;
+
+  if (--mod->ref_count > 0)
+    return;
+
+  if (mod->fini)
+    (mod->fini) ();
+  
+  pupa_dl_remove (mod);
+  pupa_dl_unregister_symbols (mod);
+  
+  for (dep = mod->dep; dep; dep = depn)
+    {
+      depn = dep->next;
+      pupa_dl_unload (dep->mod);
+      pupa_free (dep);
+    }
+
+  for (seg = mod->segment; seg; seg = segn)
+    {
+      segn = seg->next;
+      pupa_free (seg->addr);
+      pupa_free (seg);
+    }
+  
+  pupa_free (mod->name);
+  pupa_free (mod);
+}
+
+void
+pupa_dl_init (const char *dir)
+{
+  pupa_dl_dir = (char *) dir;
+}
diff --git a/kern/err.c b/kern/err.c
new file mode 100644 (file)
index 0000000..7e2d103
--- /dev/null
@@ -0,0 +1,61 @@
+/* err.c - error handling routines */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/err.h>
+#include <pupa/misc.h>
+#include <stdarg.h>
+
+#define PUPA_MAX_ERRMSG        256
+
+pupa_err_t pupa_errno;
+char pupa_errmsg[PUPA_MAX_ERRMSG];
+
+pupa_err_t
+pupa_error (pupa_err_t n, const char *fmt, ...)
+{
+  va_list ap;
+  
+  pupa_errno = n;
+
+  va_start (ap, fmt);
+  pupa_vsprintf (pupa_errmsg, fmt, ap);
+  va_end (ap);
+
+  return n;
+}
+
+void
+pupa_fatal (const char *fmt, ...)
+{
+  va_list ap;
+
+  va_start (ap, fmt);
+  pupa_vprintf (fmt, ap);
+  va_end (ap);
+
+  pupa_stop ();
+}
+
+void
+pupa_print_error (void)
+{
+  if (pupa_errno != PUPA_ERR_NONE)
+    pupa_printf ("error: %s\n", pupa_errmsg);
+}
diff --git a/kern/file.c b/kern/file.c
new file mode 100644 (file)
index 0000000..7d95ba5
--- /dev/null
@@ -0,0 +1,158 @@
+/* file.c - file I/O functions */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/misc.h>
+#include <pupa/err.h>
+#include <pupa/file.h>
+#include <pupa/mm.h>
+#include <pupa/fs.h>
+#include <pupa/device.h>
+
+/* Get the device part of the filename NAME. It is enclosed by parentheses.  */
+char *
+pupa_file_get_device_name (const char *name)
+{
+  if (name[0] == '(')
+    {
+      char *p = pupa_strchr (name, ')');
+      char *ret;
+      
+      if (! p)
+       {
+         pupa_error (PUPA_ERR_BAD_FILENAME, "missing `)'");
+         return 0;
+       }
+
+      ret = (char *) pupa_malloc (p - name);
+      if (! ret)
+       return 0;
+      
+      pupa_memcpy (ret, name + 1, p - name - 1);
+      ret[p - name - 1] = '\0';
+      return ret;
+    }
+
+  return 0;
+}
+
+pupa_file_t
+pupa_file_open (const char *name)
+{
+  pupa_device_t device;
+  pupa_file_t file = 0;
+  char *device_name;
+  char *file_name;
+
+  device_name = pupa_file_get_device_name (name);
+  if (pupa_errno)
+    return 0;
+
+  /* Get the file part of NAME.  */
+  file_name = pupa_strchr (name, ')');
+  if (file_name)
+    file_name++;
+  else
+    file_name = (char *) name;
+
+  device = pupa_device_open (device_name);
+  pupa_free (device_name);
+  if (! device)
+    goto fail;
+  
+  file = (pupa_file_t) pupa_malloc (sizeof (*file));
+  if (! file)
+    goto fail;
+  
+  file->device = device;
+  file->offset = 0;
+  file->data = 0;
+  file->read_hook = 0;
+    
+  if (device->disk && file_name[0] != '/')
+    /* This is a block list.  */
+    file->fs = &pupa_fs_blocklist;
+  else
+    {
+      file->fs = pupa_fs_probe (device);
+      if (! file->fs)
+       goto fail;
+    }
+
+  if ((file->fs->open) (file, file_name) != PUPA_ERR_NONE)
+    goto fail;
+
+  return file;
+
+ fail:
+  if (device)
+    pupa_device_close (device);
+
+  /* if (net) pupa_net_close (net);  */
+
+  pupa_free (file);
+  
+  return 0;
+}
+
+pupa_ssize_t
+pupa_file_read (pupa_file_t file, char *buf, pupa_ssize_t len)
+{
+  pupa_ssize_t res;
+  
+  if (len == 0 || len > file->size - file->offset)
+    len = file->size - file->offset;
+
+  if (len == 0)
+    return 0;
+  
+  res = (file->fs->read) (file, buf, len);
+  if (res > 0)
+    file->offset += res;
+
+  return res;
+}
+
+pupa_err_t
+pupa_file_close (pupa_file_t file)
+{
+  if (file->fs->close)
+    (file->fs->close) (file);
+
+  pupa_device_close (file->device);
+  pupa_free (file);
+  return pupa_errno;
+}
+
+pupa_ssize_t
+pupa_file_seek (pupa_file_t file, pupa_ssize_t offset)
+{
+  pupa_ssize_t old;
+
+  if (offset < 0 || offset >= file->size)
+    {
+      pupa_error (PUPA_ERR_OUT_OF_RANGE,
+                 "attempt to seek outside of the file");
+      return -1;
+    }
+  
+  old = file->offset;
+  file->offset = offset;
+  return old;
+}
diff --git a/kern/fs.c b/kern/fs.c
new file mode 100644 (file)
index 0000000..652fc55
--- /dev/null
+++ b/kern/fs.c
@@ -0,0 +1,224 @@
+/* fs.c - filesystem manager */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/disk.h>
+#include <pupa/net.h>
+#include <pupa/fs.h>
+#include <pupa/file.h>
+#include <pupa/err.h>
+#include <pupa/misc.h>
+#include <pupa/types.h>
+#include <pupa/mm.h>
+#include <pupa/term.h>
+
+static pupa_fs_t pupa_fs_list;
+
+void
+pupa_fs_register (pupa_fs_t fs)
+{
+  fs->next = pupa_fs_list;
+  pupa_fs_list = fs;
+}
+
+void
+pupa_fs_unregister (pupa_fs_t fs)
+{
+  pupa_fs_t *p, q;
+
+  for (p = &pupa_fs_list, q = *p; q; p = &(q->next), q = q->next)
+    if (q == fs)
+      {
+       *p = q->next;
+       break;
+      }
+}
+
+void
+pupa_fs_iterate (int (*hook) (const pupa_fs_t fs))
+{
+  pupa_fs_t p;
+
+  for (p = pupa_fs_list; p; p = p->next)
+    if (hook (p))
+      break;
+}
+
+pupa_fs_t
+pupa_fs_probe (pupa_device_t device)
+{
+  pupa_fs_t p;
+  auto int dummy_func (const char *filename, int dir);
+
+  int dummy_func (const char *filename __attribute__ ((unused)),
+                 int dir __attribute__ ((unused)))
+    {
+      return 1;
+    }
+
+  if (device->disk)
+    {
+      for (p = pupa_fs_list; p; p = p->next)
+       {
+         (p->dir) (device, "/", dummy_func);
+         if (pupa_errno == PUPA_ERR_NONE)
+           return p;
+         
+         if (pupa_errno != PUPA_ERR_BAD_FS)
+           return 0;
+         
+         pupa_errno = PUPA_ERR_NONE;
+       }
+    }
+  else if (device->net->fs)
+    return device->net->fs;
+
+  pupa_error (PUPA_ERR_UNKNOWN_FS, "unknown filesystem");
+  return 0;
+}
+
+\f
+
+/* Block list support routines.  */
+
+struct pupa_fs_block
+{
+  unsigned long offset;
+  unsigned long length;
+};
+
+static pupa_err_t
+pupa_fs_blocklist_open (pupa_file_t file, const char *name)
+{
+  char *p = (char *) name;
+  unsigned num = 0;
+  unsigned i;
+  pupa_disk_t disk = file->device->disk;
+  struct pupa_fs_block *blocks;
+  
+  /* First, count the number of blocks.  */
+  do
+    {
+      num++;
+      p = pupa_strchr (p, ',');
+    }
+  while (p);
+
+  /* Allocate a block list.  */
+  blocks = pupa_malloc (sizeof (struct pupa_fs_block) * (num + 1));
+  if (! blocks)
+    return 0;
+
+  file->size = 0;
+  p = (char *) name;
+  for (i = 0; i < num; i++)
+    {
+      if (*p != '+')
+       {
+         blocks[i].offset = pupa_strtoul (p, &p, 0);
+         if (pupa_errno != PUPA_ERR_NONE || *p != '+')
+           {
+             pupa_error (PUPA_ERR_BAD_FILENAME,
+                         "invalid file name `%s'", name);
+             goto fail;
+           }
+       }
+      else
+       blocks[i].offset = 0;
+
+      p++;
+      blocks[i].length = pupa_strtoul (p, &p, 0);
+      if (pupa_errno != PUPA_ERR_NONE
+         || blocks[i].length == 0
+         || (*p && *p != ',' && ! pupa_isspace (*p)))
+       {
+         pupa_error (PUPA_ERR_BAD_FILENAME,
+                     "invalid file name `%s'", name);
+         goto fail;
+       }
+
+      if (disk->total_sectors < blocks[i].offset + blocks[i].length)
+       {
+         pupa_error (PUPA_ERR_BAD_FILENAME, "beyond the total sectors");
+         goto fail;
+       }
+      
+      file->size += (blocks[i].length << PUPA_DISK_SECTOR_BITS);
+      p++;
+    }
+
+  blocks[i].length = 0;
+  file->data = blocks;
+  
+  return PUPA_ERR_NONE;
+
+ fail:
+  pupa_free (blocks);
+  return pupa_errno;
+}
+
+static pupa_ssize_t
+pupa_fs_blocklist_read (pupa_file_t file, char *buf, pupa_ssize_t len)
+{
+  struct pupa_fs_block *p;
+  unsigned long sector;
+  unsigned long offset;
+  pupa_ssize_t ret = 0;
+
+  if (len > file->size - file->offset)
+    len = file->size - file->offset;
+
+  sector = (file->offset >> PUPA_DISK_SECTOR_BITS);
+  offset = (file->offset & (PUPA_DISK_SECTOR_SIZE - 1));
+  for (p = file->data; p->length && len > 0; p++)
+    {
+      if (sector < p->length)
+       {
+         pupa_ssize_t size;
+
+         size = len;
+         if (((size + offset + PUPA_DISK_SECTOR_SIZE - 1)
+              >> PUPA_DISK_SECTOR_BITS) > p->length - sector)
+           size = ((p->length - sector) << PUPA_DISK_SECTOR_BITS) - offset;
+         
+         if (pupa_disk_read (file->device->disk, p->offset + sector, offset,
+                             size, buf) != PUPA_ERR_NONE)
+           return -1;
+         
+         ret += size;
+         len -= size;
+         sector -= ((size + offset) >> PUPA_DISK_SECTOR_BITS);
+         offset = ((size + offset) & (PUPA_DISK_SECTOR_SIZE - 1));
+       }
+      else
+       sector -= p->length;
+    }
+
+  return ret;
+}
+
+struct pupa_fs pupa_fs_blocklist =
+  {
+    .name = "blocklist",
+    .dir = 0,
+    .open = pupa_fs_blocklist_open,
+    .read = pupa_fs_blocklist_read,
+    .close = 0,
+    .next = 0
+  };
diff --git a/kern/i386/dl.c b/kern/i386/dl.c
new file mode 100644 (file)
index 0000000..bdd6dd9
--- /dev/null
@@ -0,0 +1,126 @@
+/* dl-386.c - arch-dependent part of loadable module support */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/dl.h>
+#include <pupa/elf.h>
+#include <pupa/misc.h>
+#include <pupa/err.h>
+
+/* Check if EHDR is a valid ELF header.  */
+int
+pupa_arch_dl_check_header (void *ehdr, unsigned size)
+{
+  Elf32_Ehdr *e = ehdr;
+
+  /* Check the header size.  */
+  if (size < sizeof (Elf32_Ehdr))
+    return 0;
+
+  /* Check the magic numbers.  */
+  if (e->e_ident[EI_MAG0] != ELFMAG0
+      || e->e_ident[EI_MAG1] != ELFMAG1
+      || e->e_ident[EI_MAG2] != ELFMAG2
+      || e->e_ident[EI_MAG3] != ELFMAG3
+      || e->e_version != EV_CURRENT
+      || e->e_ident[EI_CLASS] != ELFCLASS32
+      || e->e_ident[EI_DATA] != ELFDATA2LSB
+      || e->e_machine != EM_386
+      || e->e_type != ET_REL)
+    return 0;
+
+  /* Make sure that every section is within the core.  */
+  if (size < e->e_shoff + e->e_shentsize * e->e_shnum)
+    return 0;
+
+  return 1;
+}
+
+/* Relocate symbols.  */
+pupa_err_t
+pupa_arch_dl_relocate_symbols (pupa_dl_t mod, void *ehdr)
+{
+  Elf32_Ehdr *e = ehdr;
+  Elf32_Shdr *s;
+  Elf32_Sym *symtab;
+  Elf32_Word entsize;
+  unsigned i;
+
+  /* Find a symbol table.  */
+  for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf32_Shdr *) ((char *) s + e->e_shentsize))
+    if (s->sh_type == SHT_SYMTAB)
+      break;
+
+  if (i == e->e_shnum)
+    return pupa_error (PUPA_ERR_BAD_MODULE, "no symtab found");
+  
+  symtab = (Elf32_Sym *) ((char *) e + s->sh_offset);
+  entsize = s->sh_entsize;
+
+  for (i = 0, s = (Elf32_Shdr *) ((char *) e + e->e_shoff);
+       i < e->e_shnum;
+       i++, s = (Elf32_Shdr *) ((char *) s + e->e_shentsize))
+    if (s->sh_type == SHT_REL)
+      {
+       pupa_dl_segment_t seg;
+
+       /* Find the target segment.  */
+       for (seg = mod->segment; seg; seg = seg->next)
+         if (seg->section == s->sh_info)
+           break;
+
+       if (seg)
+         {
+           Elf32_Rel *rel, *max;
+           
+           for (rel = (Elf32_Rel *) ((char *) e + s->sh_offset),
+                  max = rel + s->sh_size / s->sh_entsize;
+                rel < max;
+                rel++)
+             {
+               Elf32_Word *addr;
+               Elf32_Sym *sym;
+               
+               if (seg->size < rel->r_offset)
+                 return pupa_error (PUPA_ERR_BAD_MODULE,
+                                    "reloc offset is out of the segment");
+               
+               addr = (Elf32_Word *) ((char *) seg->addr + rel->r_offset);
+               sym = (Elf32_Sym *) ((char *) symtab
+                                    + entsize * ELF32_R_SYM (rel->r_info));
+               
+               switch (ELF32_R_TYPE (rel->r_info))
+                 {
+                 case R_386_32:
+                   *addr += sym->st_value;
+                   break;
+
+                 case R_386_PC32:
+                   *addr += (sym->st_value - (Elf32_Word) seg->addr
+                             - rel->r_offset);
+                   break;
+                 }
+             }
+         }
+      }
+
+  return PUPA_ERR_NONE;
+}
diff --git a/kern/i386/pc/init.c b/kern/i386/pc/init.c
new file mode 100644 (file)
index 0000000..589696e
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/kernel.h>
+#include <pupa/mm.h>
+#include <pupa/machine/init.h>
+#include <pupa/machine/memory.h>
+#include <pupa/machine/console.h>
+#include <pupa/machine/biosdisk.h>
+#include <pupa/types.h>
+#include <pupa/err.h>
+
+void
+pupa_machine_init (void)
+{
+  pupa_uint32_t cont;
+  struct pupa_machine_mmap_entry entry;
+  pupa_size_t lower_mem = (pupa_get_memsize (0) << 10);
+  pupa_addr_t end_addr = pupa_get_end_addr ();
+
+  /* Initialize the console as early as possible.  */
+  pupa_console_init ();
+  
+  /* Sanity check.  */
+  if (lower_mem < PUPA_MEMORY_MACHINE_RESERVED_END)
+    pupa_fatal ("too small memory");
+  
+  /* Turn on Gate A20 to access >1MB.  */
+  pupa_gate_a20 (1);
+
+  /* Add the lower memory into free memory.  */
+  if (lower_mem >= PUPA_MEMORY_MACHINE_RESERVED_END)
+    pupa_mm_init_region ((void *) PUPA_MEMORY_MACHINE_RESERVED_END,
+                        lower_mem - PUPA_MEMORY_MACHINE_RESERVED_END);
+  
+  pupa_mm_init_region ((void *) end_addr,
+                      PUPA_MEMORY_MACHINE_RESERVED_START - end_addr);
+
+  /* Check if pupa_get_mmap_entry works.  */
+  cont = pupa_get_mmap_entry (&entry, 0);
+
+  if (entry.size)
+    do
+      {
+       /* Avoid the lower memory.  */
+       if (entry.addr < 0x100000)
+         {
+           if (entry.len <= 0x100000 - entry.addr)
+             goto next;
+
+           entry.len -= 0x100000 - entry.addr;
+           entry.addr = 0x100000;
+         }
+       
+       /* Ignore >4GB.  */
+       if (entry.addr <= 0xFFFFFFFF && entry.type == 1)
+         {
+           pupa_addr_t addr;
+           pupa_size_t len;
+
+           addr = (pupa_addr_t) entry.addr;
+           len = ((addr + entry.len > 0xFFFFFFFF)
+                  ? 0xFFFFFFFF - addr
+                  : (pupa_size_t) entry.len);
+           pupa_mm_init_region ((void *) addr, len);
+         }
+       
+      next:
+       if (! cont)
+         break;
+       
+       cont = pupa_get_mmap_entry (&entry, cont);
+      }
+    while (entry.size);
+  else
+    {
+      pupa_uint32_t eisa_mmap = pupa_get_eisa_mmap ();
+
+      if (eisa_mmap)
+       {
+         if ((eisa_mmap & 0xFFFF) == 0x3C00)
+           pupa_mm_init_region ((void *) 0x100000,
+                                (eisa_mmap << 16) + 0x100000 * 15);
+         else
+           {
+             pupa_mm_init_region ((void *) 0x100000,
+                                  (eisa_mmap & 0xFFFF) << 10);
+             pupa_mm_init_region ((void *) 0x1000000, eisa_mmap << 16);
+           }
+       }
+      else
+       pupa_mm_init_region ((void *) 0x100000,
+                            (pupa_size_t) pupa_get_memsize (1) << 10);
+    }
+
+  /* The memory system was initialized, thus register built-in devices.  */
+  pupa_biosdisk_init ();
+}
diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S
new file mode 100644 (file)
index 0000000..ecc97f3
--- /dev/null
@@ -0,0 +1,1377 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc.
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ * Note: These functions defined in this file may be called from C.
+ *       Be careful of that you must not modify some registers. Quote
+ *       from gcc-2.95.2/gcc/config/i386/i386.h:
+       
+   1 for registers not available across function calls.
+   These must include the FIXED_REGISTERS and also any
+   registers that can be used without being saved.
+   The latter must include the registers where values are returned
+   and the register where structure-value addresses are passed.
+   Aside from that, you can include as many other registers as you like.
+
+  ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg
+{  1, 1, 1, 0, 0, 0, 0, 1, 1,  1,  1,  1,  1,  1,  1,  1,  1 }
+ */
+
+#include <config.h>
+#include <pupa/symbol.h>
+#include <pupa/boot.h>
+#include <pupa/machine/boot.h>
+#include <pupa/machine/memory.h>
+#include <pupa/machine/console.h>
+
+#define ABS(x) ((x) - EXT_C(start) + PUPA_BOOT_MACHINE_KERNEL_ADDR + 0x200)
+       
+       .file   "startup.S"
+
+       .text
+
+       /* Tell GAS to generate 16-bit instructions so that this code works
+          in real mode. */
+       .code16
+
+       .globl  start, _start
+start:
+_start:
+       /*
+        *  Guarantee that "main" is loaded at 0x0:0x8200.
+        */
+       ljmp $0, $ABS(codestart)
+
+       /*
+        *  Compatibility version number
+        *
+        *  These MUST be at byte offset 6 and 7 of the executable
+        *  DO NOT MOVE !!!
+        */
+       . = EXT_C(start) + 0x6
+       .byte   PUPA_BOOT_VERSION_MAJOR, PUPA_BOOT_VERSION_MINOR
+
+       /*
+        *  This is a special data area 8 bytes from the beginning.
+        */
+
+       . = EXT_C(start) + 0x8
+
+VARIABLE(pupa_total_module_size)
+       .long   0
+VARIABLE(pupa_kernel_image_size)
+       .long   0
+VARIABLE(install_partition)
+       .long   0xFFFFFF
+VARIABLE(version_string)
+       .string PACKAGE_VERSION
+VARIABLE(config_file)
+       .string "/boot/pupa/puparc"
+
+       /*
+        *  Leave some breathing room for the config file name.
+        */
+
+       . = EXT_C(start) + 0x70
+
+/* the real mode code continues... */
+codestart:
+       cli             /* we're not safe here! */
+
+       /* set up %ds, %ss, and %es */
+       xorw    %ax, %ax
+       movw    %ax, %ds
+       movw    %ax, %ss
+       movw    %ax, %es
+
+       /* set up the real mode/BIOS stack */
+       movl    $PUPA_MEMORY_MACHINE_REAL_STACK, %ebp
+       movl    %ebp, %esp
+
+       sti             /* we're safe again */
+
+       /* save boot drive reference */
+       ADDR32  movb    %dl, EXT_C(pupa_boot_drive)
+
+       /* reset disk system (%ah = 0) */
+       int     $0x13
+
+       /* transition to protected mode */
+       DATA32  call real_to_prot
+
+       /* The ".code32" directive takes GAS out of 16-bit mode. */
+       .code32
+
+       /* copy modules before cleaning out the bss */
+       movl    EXT_C(pupa_total_module_size), %ecx
+       movl    EXT_C(pupa_kernel_image_size), %esi
+       addl    %ecx, %esi
+       addl    $START_SYMBOL, %esi
+       decl    %esi
+       movl    $END_SYMBOL, %edi
+       addl    %ecx, %edi
+       decl    %edi
+       std
+       rep
+       movsb
+       
+       /* clean out the bss */
+       movl    $BSS_START_SYMBOL, %edi
+
+       /* compute the bss length */
+       movl    $END_SYMBOL, %ecx
+       subl    %edi, %ecx
+               
+       /* clean out */
+       cld
+       rep
+       stosb
+       
+       /*
+        *  Call the start of main body of C code.
+        */
+       call EXT_C(pupa_main)
+
+
+/*
+ *  This call is special...  it never returns...  in fact it should simply
+ *  hang at this point!
+ */
+
+FUNCTION(pupa_stop)
+       call    prot_to_real
+
+       /*
+        * This next part is sort of evil.  It takes advantage of the
+        * byte ordering on the x86 to work in either 16-bit or 32-bit
+        * mode, so think about it before changing it.
+        */
+
+FUNCTION(pupa_hard_stop)
+       hlt
+       jmp EXT_C(pupa_hard_stop)
+
+
+/*
+ * pupa_stop_floppy()
+ *
+ * Stop the floppy drive from spinning, so that other software is
+ * jumped to with a known state.
+ */
+FUNCTION(pupa_stop_floppy)
+       movw    $0x3F2, %dx
+       xorb    %al, %al
+       outb    %al, %dx
+       ret
+
+/*
+ * pupa_reboot()
+ *
+ * Reboot the system. At the moment, rely on BIOS.
+ */
+FUNCTION(pupa_reboot)
+       call    prot_to_real
+       .code16
+       /* cold boot */
+       movw    $0x0472, %di
+       movw    %ax, (%di)
+       ljmp    $0xFFFF, $0x0000
+       .code32
+       
+/*
+ * pupa_halt(int no_apm)
+ *
+ * Halt the system, using APM if possible. If NO_APM is true, don't use
+ * APM even if it is available.
+ */
+FUNCTION(pupa_halt)
+       /* get the argument */
+       movl    4(%esp), %eax
+       
+       /* see if zero */
+       testl   %eax, %eax
+       jnz     EXT_C(pupa_stop)
+
+       call    prot_to_real
+       .code16
+       
+       /* detect APM */
+       movw    $0x5300, %ax
+       xorw    %bx, %bx
+       int     $0x15
+       jc      EXT_C(pupa_hard_stop)
+       /* don't check %bx for buggy BIOSes... */
+
+       /* disconnect APM first */
+       movw    $0x5304, %ax
+       xorw    %bx, %bx
+       int     $0x15
+
+       /* connect APM */
+       movw    $0x5301, %ax
+       xorw    %bx, %bx
+       int     $0x15
+       jc      EXT_C(pupa_hard_stop)
+
+       /* set APM protocol level - 1.1 or bust. (this covers APM 1.2 also) */
+       movw    $0x530E, %ax
+       xorw    %bx, %bx
+       movw    $0x0101, %cx
+       int     $0x15
+       jc      EXT_C(pupa_hard_stop)
+       
+       /* set the power state to off */
+       movw    $0x5307, %ax
+       movw    $1, %bx
+       movw    $3, %cx
+       int     $0x15
+
+       /* shouldn't reach here */
+       jmp     EXT_C(pupa_hard_stop)
+       .code32
+       
+       
+/*
+ *  void pupa_chainloader_real_boot (int drive, void *part_addr)
+ *
+ *  This starts another boot loader.
+ */
+
+FUNCTION(pupa_chainloader_real_boot)
+       /* no need to save anything, just use %esp */
+
+       /* ESI must point to a partition table entry */
+       movl    8(%esp), %esi
+
+       /* set up to pass boot drive */
+       movl    4(%esp), %edx
+
+       /* Turn off Gate A20 */
+       pushl   $0
+       call    EXT_C(pupa_gate_a20)
+       
+       call    prot_to_real
+       .code16
+       ljmp    $0, $PUPA_MEMORY_MACHINE_BOOT_LOADER_ADDR
+       .code32
+
+
+/*
+ *  These next two routines, "real_to_prot" and "prot_to_real" are structured
+ *  in a very specific way.  Be very careful when changing them.
+ *
+ *  NOTE:  Use of either one messes up %eax and %ebp.
+ */
+
+real_to_prot:
+       .code16
+       cli
+
+       /* load the GDT register */
+       DATA32  ADDR32  lgdt    gdtdesc
+
+       /* turn on protected mode */
+       movl    %cr0, %eax
+       orl     $PUPA_MEMORY_MACHINE_CR0_PE_ON, %eax
+       movl    %eax, %cr0
+
+       /* jump to relocation, flush prefetch queue, and reload %cs */
+       DATA32  ljmp    $PUPA_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg
+
+       .code32
+protcseg:
+       /* reload other segment registers */
+       movw    $PUPA_MEMORY_MACHINE_PROT_MODE_DSEG, %ax
+       movw    %ax, %ds
+       movw    %ax, %es
+       movw    %ax, %fs
+       movw    %ax, %gs
+       movw    %ax, %ss
+
+       /* put the return address in a known safe location */
+       movl    (%esp), %eax
+       movl    %eax, PUPA_MEMORY_MACHINE_REAL_STACK
+
+       /* get protected mode stack */
+       movl    protstack, %eax
+       movl    %eax, %esp
+       movl    %eax, %ebp
+
+       /* get return address onto the right stack */
+       movl    PUPA_MEMORY_MACHINE_REAL_STACK, %eax
+       movl    %eax, (%esp)
+
+       /* zero %eax */
+       xorl    %eax, %eax
+
+       /* return on the old (or initialized) stack! */
+       ret
+
+
+prot_to_real:
+       /* just in case, set GDT */
+       lgdt    gdtdesc
+
+       /* save the protected mode stack */
+       movl    %esp, %eax
+       movl    %eax, protstack
+
+       /* get the return address */
+       movl    (%esp), %eax
+       movl    %eax, PUPA_MEMORY_MACHINE_REAL_STACK
+
+       /* set up new stack */
+       movl    $PUPA_MEMORY_MACHINE_REAL_STACK, %eax
+       movl    %eax, %esp
+       movl    %eax, %ebp
+
+       /* set up segment limits */
+       movw    $PUPA_MEMORY_MACHINE_PSEUDO_REAL_DSEG, %ax
+       movw    %ax, %ds
+       movw    %ax, %es
+       movw    %ax, %fs
+       movw    %ax, %gs
+       movw    %ax, %ss
+
+       /* this might be an extra step */
+       /* jump to a 16 bit segment */
+       ljmp    $PUPA_MEMORY_MACHINE_PSEUDO_REAL_CSEG, $tmpcseg
+
+tmpcseg:
+       .code16
+
+       /* clear the PE bit of CR0 */
+       movl    %cr0, %eax
+       andl    $(~PUPA_MEMORY_MACHINE_CR0_PE_ON), %eax
+       movl    %eax, %cr0
+
+       /* flush prefetch queue, reload %cs */
+       DATA32  ljmp    $0, $realcseg
+
+realcseg:
+       /* we are in real mode now
+        * set up the real mode segment registers : DS, SS, ES
+        */
+       /* zero %eax */
+       xorl    %eax, %eax
+
+       movw    %ax, %ds
+       movw    %ax, %es
+       movw    %ax, %fs
+       movw    %ax, %gs
+       movw    %ax, %ss
+
+       /* restore interrupts */
+       sti
+
+       /* return on new stack! */
+       DATA32  ret
+
+       .code32
+
+
+/*
+ *   int pupa_biosdisk_rw_int13_extensions (int ah, int drive, void *dap)
+ *
+ *   Call IBM/MS INT13 Extensions (int 13 %ah=AH) for DRIVE. DAP
+ *   is passed for disk address packet. If an error occurs, return
+ *   non-zero, otherwise zero.
+ */
+
+FUNCTION(pupa_biosdisk_rw_int13_extensions)
+       pushl   %ebp
+       movl    %esp, %ebp
+
+       pushl   %esi
+
+       /* compute the address of disk_address_packet */
+       movl    0x10(%ebp), %eax
+       movw    %ax, %si
+       xorw    %ax, %ax
+       shrl    $4, %eax
+       movw    %ax, %cx        /* save the segment to cx */
+
+       /* drive */
+       movb    0xc(%ebp), %dl
+       /* ah */
+       movb    0x8(%ebp), %dh
+       /* enter real mode */
+       call    prot_to_real
+       
+       .code16
+       movb    %dh, %ah
+       movw    %cx, %ds
+       int     $0x13           /* do the operation */
+       movb    %ah, %dl        /* save return value */
+       /* clear the data segment */
+       xorw    %ax, %ax
+       movw    %ax, %ds
+       /* back to protected mode */
+       DATA32  call    real_to_prot
+       .code32
+
+       movb    %dl, %al        /* return value in %eax */
+
+       popl    %esi
+       popl    %ebp
+
+       ret
+       
+/*
+ *   int pupa_biosdisk_rw_standard (int ah, int drive, int coff, int hoff,
+ *                                  int soff, int nsec, int segment)
+ *
+ *   Call standard and old INT13 (int 13 %ah=AH) for DRIVE. Read/write
+ *   NSEC sectors from COFF/HOFF/SOFF into SEGMENT. If an error occurs,
+ *   return non-zero, otherwise zero.
+ */
+
+FUNCTION(pupa_biosdisk_rw_standard)
+       pushl   %ebp
+       movl    %esp, %ebp
+
+       pushl   %ebx
+       pushl   %edi
+       pushl   %esi
+
+       /* set up CHS information */
+       movl    0x10(%ebp), %eax
+       movb    %al, %ch
+       movb    0x18(%ebp), %al
+       shlb    $2, %al
+       shrw    $2, %ax
+       movb    %al, %cl
+       movb    0x14(%ebp), %dh
+       /* drive */
+       movb    0xc(%ebp), %dl
+       /* segment */
+       movw    0x20(%ebp), %bx
+       /* save nsec and ah to %di */
+       movb    0x8(%ebp), %ah
+       movb    0x1c(%ebp), %al
+       movw    %ax, %di
+       /* enter real mode */
+       call    prot_to_real
+
+       .code16
+       movw    %bx, %es
+       xorw    %bx, %bx
+       movw    $3, %si         /* attempt at least three times */
+
+1:     
+       movw    %di, %ax
+       int     $0x13           /* do the operation */
+       jnc     2f              /* check if successful */
+
+       movb    %ah, %bl        /* save return value */
+       /* if fail, reset the disk system */
+       xorw    %ax, %ax
+       int     $0x13
+       
+       decw    %si
+       cmpw    $0, %si
+       je      2f
+       xorb    %bl, %bl
+       jmp     1b              /* retry */
+2:     
+       /* back to protected mode */
+       DATA32  call    real_to_prot
+       .code32
+
+       movb    %bl, %al        /* return value in %eax */
+       
+       popl    %esi
+       popl    %edi
+       popl    %ebx
+       popl    %ebp
+
+       ret
+
+
+/*
+ *   int pupa_biosdisk_check_int13_extensions (int drive)
+ *
+ *   Check if LBA is supported for DRIVE. If it is supported, then return
+ *   the major version of extensions, otherwise zero.
+ */
+
+FUNCTION(pupa_biosdisk_check_int13_extensions)
+       pushl   %ebp
+       movl    %esp, %ebp
+
+       pushl   %ebx
+
+       /* drive */
+       movb    0x8(%ebp), %dl
+       /* enter real mode */
+       call    prot_to_real
+
+       .code16
+       movb    $0x41, %ah
+       movw    $0x55aa, %bx
+       int     $0x13           /* do the operation */
+       
+       /* check the result */
+       jc      1f
+       cmpw    $0xaa55, %bx
+       jne     1f
+
+       movb    %ah, %bl        /* save the major version into %bl */
+
+       /* check if AH=0x42 is supported */
+       andw    $1, %cx
+       jnz     2f
+       
+1:
+       xorb    %bl, %bl
+2:
+       /* back to protected mode */
+       DATA32  call    real_to_prot
+       .code32
+
+       movb    %bl, %al        /* return value in %eax */
+
+       popl    %ebx
+       popl    %ebp
+
+       ret
+
+
+/*
+ *   int pupa_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp)
+ *
+ *   Return the geometry of DRIVE in a drive parameters, DRP. If an error
+ *   occurs, then return non-zero, otherwise zero.
+ */
+
+FUNCTION(pupa_biosdisk_get_diskinfo_int13_extensions)
+       pushl   %ebp
+       movl    %esp, %ebp
+
+       pushl   %ebx
+       pushl   %esi
+
+       /* compute the address of drive parameters */
+       movl    0xc(%ebp), %eax
+       movw    %ax, %si
+       xorw    %ax, %ax
+       shrl    $4, %eax
+       movw    %ax, %bx        /* save the segment into %bx */
+       /* drive */
+       movb    0x8(%ebp), %dl
+       /* enter real mode */
+       call    prot_to_real
+
+       .code16
+       movb    $0x48, %ah
+       movw    %bx, %ds
+       int     $0x13           /* do the operation */
+       movb    %ah, %bl        /* save return value in %bl */
+       /* clear the data segment */
+       xorw    %ax, %ax
+       movw    %ax, %ds
+       /* back to protected mode */
+       DATA32  call    real_to_prot
+       .code32
+
+       movb    %bl, %al        /* return value in %eax */
+
+       popl    %esi
+       popl    %ebx
+       popl    %ebp
+       
+       ret
+
+
+/*
+ *   int pupa_biosdisk_get_diskinfo_standard (int drive,
+ *                                            unsigned long *cylinders, 
+ *                                            unsigned long *heads,
+ *                                            unsigned long *sectors)
+ *
+ *   Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an
+ *   error occurs, then return non-zero, otherwise zero.
+ */
+
+FUNCTION(pupa_biosdisk_get_diskinfo_standard)
+       pushl   %ebp
+       movl    %esp, %ebp
+
+       pushl   %ebx
+       pushl   %edi
+
+       /* drive */
+       movb    0x8(%ebp), %dl
+       /* enter real mode */
+       call    prot_to_real
+
+       .code16
+       movb    $0x8, %ah
+       int     $0x13           /* do the operation */
+       /* check if successful */
+       testb   %ah, %ah
+       jnz     1f
+       /* bogus BIOSes may not return an error number */
+       testb   $0x3f, %cl      /* 0 sectors means no disk */
+       jnz     1f              /* if non-zero, then succeed */
+       /* XXX 0x60 is one of the unused error numbers */
+       movb    $0x60, %ah
+1:
+       movb    %ah, %bl        /* save return value in %bl */
+       /* back to protected mode */
+       DATA32  call    real_to_prot
+       .code32
+
+       /* restore %ebp */
+       leal    0x8(%esp), %ebp
+       
+       /* heads */
+       movb    %dh, %al
+       incl    %eax            /* the number of heads is counted from zero */
+       movl    0x10(%ebp), %edi
+       movl    %eax, (%edi)
+
+       /* sectors */
+       xorl    %eax, %eax
+       movb    %cl, %al
+       andb    $0x3f, %al
+       movl    0x14(%ebp), %edi
+       movl    %eax, (%edi)
+
+       /* cylinders */
+       shrb    $6, %cl
+       movb    %cl, %ah
+       movb    %ch, %al
+       incl    %eax            /* the number of cylinders is 
+                                  counted from zero */
+       movl    0xc(%ebp), %edi
+       movl    %eax, (%edi)
+
+       xorl    %eax, %eax
+       movb    %bl, %al        /* return value in %eax */
+
+       popl    %edi
+       popl    %ebx
+       popl    %ebp
+
+       ret
+
+
+/*
+ * int pupa_biosdisk_get_num_floppies (void)
+ */
+FUNCTION(pupa_biosdisk_get_num_floppies)
+       pushl   %ebp
+
+       xorl    %edx, %edx
+       call    prot_to_real
+       
+       .code16
+       /* reset the disk system first */
+       int     $0x13
+1:
+       stc
+       
+       /* call GET DISK TYPE */
+       movb    $0x15, %ah
+       int     $0x13
+
+       jc      2f
+
+       /* check if this drive exists */        
+       testb   $0x3, %ah
+       jz      2f
+
+       incb    %dl
+       cmpb    $2, %dl
+       jne     1b
+2:
+       DATA32  call    real_to_prot
+       .code32
+
+       movl    %edx, %eax
+       popl    %ebp
+       ret
+       
+       
+/*
+ *
+ * pupa_get_memsize(i) :  return the memory size in KB. i == 0 for conventional
+ *             memory, i == 1 for extended memory
+ *     BIOS call "INT 12H" to get conventional memory size
+ *     BIOS call "INT 15H, AH=88H" to get extended memory size
+ *             Both have the return value in AX.
+ *
+ */
+
+FUNCTION(pupa_get_memsize)
+       pushl   %ebp
+       pushl   %ebx
+
+       movl    0xc(%esp), %ebx
+
+       call    prot_to_real    /* enter real mode */
+       .code16
+
+       testl   %ebx, %ebx
+       jnz     xext
+
+       int     $0x12
+       jmp     xdone
+
+xext:
+       movb    $0x88, %ah
+       int     $0x15
+
+xdone:
+       movw    %ax, %bx
+
+       DATA32  call    real_to_prot
+       .code32
+
+       movw    %bx, %ax
+       popl    %ebx
+       popl    %ebp
+       ret
+
+
+/*
+ *
+ * pupa_get_eisa_mmap() :  return packed EISA memory map, lower 16 bits is
+ *             memory between 1M and 16M in 1K parts, upper 16 bits is
+ *             memory above 16M in 64K parts.  If error, return zero.
+ *     BIOS call "INT 15H, AH=E801H" to get EISA memory map,
+ *             AX = memory between 1M and 16M in 1K parts.
+ *             BX = memory above 16M in 64K parts.
+ *
+ */
+
+FUNCTION(pupa_get_eisa_mmap)
+       pushl   %ebp
+       pushl   %ebx
+
+       call    prot_to_real    /* enter real mode */
+       .code16
+
+       movw    $0xe801, %ax
+       int     $0x15
+
+       shll    $16, %ebx
+       movw    %ax, %bx
+
+       DATA32  call    real_to_prot
+       .code32
+
+       cmpb    $0x86, %bh
+       je      xnoteisa
+
+       movl    %ebx, %eax
+
+xnoteisa:
+       popl    %ebx
+       popl    %ebp
+       ret
+
+/*
+ *
+ * pupa_get_mmap_entry(addr, cont) : address and old continuation value (zero to
+ *             start), for the Query System Address Map BIOS call.
+ *
+ *  Sets the first 4-byte int value of "addr" to the size returned by
+ *  the call.  If the call fails, sets it to zero.
+ *
+ *     Returns:  new (non-zero) continuation value, 0 if done.
+ */
+
+FUNCTION(pupa_get_mmap_entry)
+       push    %ebp
+       push    %ebx
+       push    %edi
+       push    %esi
+
+       /* place address (+4) in ES:DI */
+       movl    0x14(%esp), %eax
+       addl    $4, %eax
+       movl    %eax, %edi
+       andl    $0xf, %edi
+       shrl    $4, %eax
+       movl    %eax, %esi
+
+       /* set continuation value */
+       movl    0x18(%esp), %ebx
+
+       /* set default maximum buffer size */
+       movl    $0x14, %ecx
+
+       /* set EDX to 'SMAP' */
+       movl    $0x534d4150, %edx
+
+       call    prot_to_real    /* enter real mode */
+       .code16
+
+       movw    %si, %es
+       movl    $0xe820, %eax
+       int     $0x15
+
+       DATA32  jc      xnosmap
+
+       cmpl    $0x534d4150, %eax
+       jne     xnosmap
+
+       cmpl    $0x14, %ecx
+       jl      xnosmap
+
+       cmpl    $0x400, %ecx
+       jg      xnosmap
+
+       jmp     xsmap
+
+xnosmap:
+       xorl    %ecx, %ecx
+
+xsmap:
+       DATA32  call    real_to_prot
+       .code32
+
+       /* write length of buffer (zero if error) into "addr" */
+       movl    0x14(%esp), %eax
+       movl    %ecx, (%eax)
+
+       /* set return value to continuation */
+       movl    %ebx, %eax
+
+       pop     %esi
+       pop     %edi
+       pop     %ebx
+       pop     %ebp
+       ret
+
+       
+/*
+ * pupa_gate_a20(int on)
+ *
+ * Gate address-line 20 for high memory.
+ *
+ * This routine is probably overconservative in what it does, but so what?
+ *
+ * It also eats any keystrokes in the keyboard buffer.  :-(
+ */
+
+FUNCTION(pupa_gate_a20)
+       pushl   %eax
+
+       call    gloop1
+
+       movb    $0xd1, %al
+       outb    $0x64
+
+gloopint1:
+       inb     $0x64
+       andb    $0x02, %al
+       jnz     gloopint1
+
+       movb    $0xdd, %al
+       cmpb    $0, 0x8(%esp)
+       jz      gdoit
+
+       orb     $0x02, %al
+gdoit:
+       outb    $0x60
+
+       call    gloop1
+
+       /* output a dummy command (USB keyboard hack) */
+       movb    $0xff, %al
+       outb    $0x64
+       call    gloop1
+       
+       popl    %eax
+       ret
+
+gloop1:
+       inb     $0x64
+       andb    $0x02, %al
+       jnz     gloop1
+
+gloop2:
+       inb     $0x64
+       andb    $0x01, %al
+       jz      gloop2ret
+       inb     $0x60
+       jmp     gloop2
+
+gloop2ret:
+       ret
+
+
+/*
+ * void pupa_console_putchar (int c)
+ *
+ * Put the character C on the console. Because GRUB wants to write a
+ * character with an attribute, this implementation is a bit tricky.
+ * If C is a control character (CR, LF, BEL, BS), use INT 10, AH = 0Eh
+ * (TELETYPE OUTPUT). Otherwise, save the original position, put a space,
+ * save the current position, restore the original position, write the
+ * character and the attribute, and restore the current position.
+ *
+ * The reason why this is so complicated is that there is no easy way to
+ * get the height of the screen, and the TELETYPE OUPUT BIOS call doesn't
+ * support setting a background attribute.
+ */
+FUNCTION(pupa_console_putchar)
+       movl    0x4(%esp), %edx
+       pusha
+       movb    EXT_C(pupa_console_cur_color), %bl
+       
+       call    prot_to_real
+       .code16
+       movb    %dl, %al
+       xorb    %bh, %bh
+
+       /* use teletype output if control character */
+       cmpb    $0x7, %al
+       je      1f
+       cmpb    $0x8, %al
+       je      1f
+       cmpb    $0xa, %al
+       je      1f
+       cmpb    $0xd, %al
+       je      1f
+
+       /* save the character and the attribute on the stack */
+       pushw   %ax
+       pushw   %bx
+       
+       /* get the current position */
+       movb    $0x3, %ah
+       int     $0x10
+
+       /* check the column with the width */
+       cmpb    $79, %dl
+       jl      2f
+       
+       /* print CR and LF, if next write will exceed the width */      
+       movw    $0x0e0d, %ax
+       int     $0x10
+       movb    $0x0a, %al
+       int     $0x10
+       
+       /* get the current position */
+       movb    $0x3, %ah
+       int     $0x10
+
+2:     
+       /* restore the character and the attribute */
+       popw    %bx
+       popw    %ax
+       
+       /* write the character with the attribute */
+       movb    $0x9, %ah
+       movw    $1, %cx
+       int     $0x10
+
+       /* move the cursor forward */
+       incb    %dl
+       movb    $0x2, %ah
+       int     $0x10
+
+       jmp     3f
+       
+1:     movb    $0x7, %bl
+       movb    $0xe, %ah
+       int     $0x10
+       
+3:     DATA32  call    real_to_prot
+       .code32
+       
+       popa
+       ret
+
+
+/*
+ * int pupa_console_getkey (void)
+ * BIOS call "INT 16H Function 00H" to read character from keyboard
+ *     Call with       %ah = 0x0
+ *     Return:         %ah = keyboard scan code
+ *                     %al = ASCII character
+ */
+
+FUNCTION(pupa_console_getkey)
+       pushl   %ebp
+
+       call    prot_to_real
+       .code16
+
+       int     $0x16
+
+       movw    %ax, %dx                /* real_to_prot uses %eax */
+       
+       DATA32  call    real_to_prot
+       .code32
+
+       movw    %dx, %ax
+
+       popl    %ebp
+       ret
+
+
+/*
+ * int pupa_console_checkkey (void)
+ *     if there is a character pending, return it; otherwise return -1
+ * BIOS call "INT 16H Function 01H" to check whether a character is pending
+ *     Call with       %ah = 0x1
+ *     Return:
+ *             If key waiting to be input:
+ *                     %ah = keyboard scan code
+ *                     %al = ASCII character
+ *                     Zero flag = clear
+ *             else
+ *                     Zero flag = set
+ */
+FUNCTION(pupa_console_checkkey)
+       pushl   %ebp
+       xorl    %edx, %edx
+       
+       call    prot_to_real    /* enter real mode */
+       .code16
+
+       movb    $0x1, %ah
+       int     $0x16
+
+       jz      notpending
+       
+       movw    %ax, %dx
+       DATA32  jmp     pending
+
+notpending:
+       decl    %edx
+
+pending:
+       DATA32  call    real_to_prot
+       .code32
+
+       movl    %edx, %eax
+
+       popl    %ebp
+       ret
+
+       
+/*
+ * pupa_uint16_t pupa_console_getxy (void)
+ * BIOS call "INT 10H Function 03h" to get cursor position
+ *     Call with       %ah = 0x03
+ *                     %bh = page
+ *      Returns         %ch = starting scan line
+ *                      %cl = ending scan line
+ *                      %dh = row (0 is top)
+ *                      %dl = column (0 is left)
+ */
+
+
+FUNCTION(pupa_console_getxy)
+       pushl   %ebp
+       pushl   %ebx                    /* save EBX */
+
+       call    prot_to_real
+       .code16
+
+        xorb   %bh, %bh                /* set page to 0 */
+       movb    $0x3, %ah
+       int     $0x10                   /* get cursor position */
+
+       DATA32  call    real_to_prot
+       .code32
+
+       movb    %dl, %ah
+       movb    %dh, %al
+
+       popl    %ebx
+       popl    %ebp
+       ret
+
+
+/*
+ * void pupa_console_gotoxy(pupa_uint8_t x, pupa_uint8_t y)
+ * BIOS call "INT 10H Function 02h" to set cursor position
+ *     Call with       %ah = 0x02
+ *                     %bh = page
+ *                      %dh = row (0 is top)
+ *                      %dl = column (0 is left)
+ */
+
+
+FUNCTION(pupa_console_gotoxy)
+       pushl   %ebp
+       pushl   %ebx                    /* save EBX */
+
+       movb    0xc(%esp), %dl           /* %dl = x */
+       movb    0x10(%esp), %dh          /* %dh = y */
+
+       call    prot_to_real
+       .code16
+
+        xorb   %bh, %bh                /* set page to 0 */
+       movb    $0x2, %ah
+       int     $0x10                   /* set cursor position */
+
+       DATA32  call    real_to_prot
+       .code32
+
+       popl    %ebx
+       popl    %ebp
+       ret
+
+       
+/*
+ * void pupa_console_cls (void)
+ * BIOS call "INT 10H Function 09h" to write character and attribute
+ *     Call with       %ah = 0x09
+ *                      %al = (character)
+ *                      %bh = (page number)
+ *                      %bl = (attribute)
+ *                      %cx = (number of times)
+ */
+
+FUNCTION(pupa_console_cls)
+       pushl   %ebp
+       pushl   %ebx                    /* save EBX */
+
+       call    prot_to_real
+       .code16
+
+       /* move the cursor to the beginning */
+       movb    $0x02, %ah
+       xorb    %bh, %bh
+       xorw    %dx, %dx
+       int     $0x10
+
+       /* write spaces to the entire screen */
+       movw    $0x0920, %ax
+       movw    $0x07, %bx
+       movw    $(80 * 25), %cx
+        int    $0x10
+
+       /* move back the cursor */
+       movb    $0x02, %ah
+       int     $0x10
+
+       DATA32  call    real_to_prot
+       .code32
+
+       popl    %ebx
+       popl    %ebp
+       ret
+
+       
+/*
+ * void pupa_console_setcursor (int on)
+ * BIOS call "INT 10H Function 01h" to set cursor type
+ *      Call with       %ah = 0x01
+ *                      %ch = cursor starting scanline
+ *                      %cl = cursor ending scanline
+ */
+
+console_cursor_state:
+       .byte   1
+console_cursor_shape:
+       .word   0
+       
+FUNCTION(pupa_console_setcursor)
+       push    %ebp
+       push    %ebx
+
+       /* check if the standard cursor shape has already been saved */
+       movw    console_cursor_shape, %ax
+       testw   %ax, %ax
+       jne     1f
+
+       call    prot_to_real
+       .code16
+
+       movb    $0x03, %ah
+       xorb    %bh, %bh
+       int     $0x10
+
+       DATA32  call    real_to_prot
+       .code32
+
+       movw    %cx, console_cursor_shape
+1:
+       /* set %cx to the designated cursor shape */
+       movw    $0x2000, %cx
+       movl    0xc(%esp), %ebx
+       testl   %ebx, %ebx
+       jz      2f
+       movw    console_cursor_shape, %cx
+2:     
+       call    prot_to_real
+       .code16
+
+       movb    $0x1, %ah
+       int     $0x10 
+
+       DATA32  call    real_to_prot
+       .code32
+
+       popl    %ebx
+       popl    %ebp
+       ret
+               
+/*
+ * pupa_getrtsecs()
+ *     if a seconds value can be read, read it and return it (BCD),
+ *      otherwise return 0xFF
+ * BIOS call "INT 1AH Function 02H" to check whether a character is pending
+ *     Call with       %ah = 0x2
+ *     Return:
+ *             If RT Clock can give correct values
+ *                     %ch = hour (BCD)
+ *                     %cl = minutes (BCD)
+ *                      %dh = seconds (BCD)
+ *                      %dl = daylight savings time (00h std, 01h daylight)
+ *                     Carry flag = clear
+ *             else
+ *                     Carry flag = set
+ *                         (this indicates that the clock is updating, or
+ *                          that it isn't running)
+ */
+FUNCTION(pupa_getrtsecs)
+       push    %ebp
+
+       call    prot_to_real    /* enter real mode */
+       .code16
+
+       clc
+       movb    $0x2, %ah
+       int     $0x1a
+
+       DATA32  jnc     gottime
+       movb    $0xff, %dh
+
+gottime:
+       DATA32  call    real_to_prot
+       .code32
+
+       movb    %dh, %al
+
+       pop     %ebp
+       ret
+
+       
+/*
+ * pupa_currticks()
+ *     return the real time in ticks, of which there are about
+ *     18-20 per second
+ */
+FUNCTION(pupa_currticks)
+       pushl   %ebp
+
+       call    prot_to_real    /* enter real mode */
+       .code16
+
+       /* %ax is already zero */
+        int    $0x1a
+
+       DATA32  call    real_to_prot
+       .code32
+
+       movl    %ecx, %eax
+       shll    $16, %eax
+       movw    %dx, %ax
+
+       popl    %ebp
+       ret
+
+
+/*
+ *  This is the area for all of the special variables.
+ */
+
+       .p2align        2       /* force 4-byte alignment */
+
+protstack:
+       .long   PUPA_MEMORY_MACHINE_PROT_STACK
+
+VARIABLE(pupa_boot_drive)
+       .long   0
+
+VARIABLE(pupa_start_addr)
+       .long   START_SYMBOL
+
+VARIABLE(pupa_end_addr)
+       .long   END_SYMBOL
+       
+VARIABLE(pupa_apm_bios_info)
+       .word   0       /* version */
+       .word   0       /* cseg */
+       .long   0       /* offset */
+       .word   0       /* cseg_16 */
+       .word   0       /* dseg_16 */
+       .word   0       /* cseg_len */
+       .word   0       /* cseg_16_len */
+       .word   0       /* dseg_16_len */
+       
+/*
+ * This is the Global Descriptor Table
+ *
+ *  An entry, a "Segment Descriptor", looks like this:
+ *
+ * 31          24         19   16                 7           0
+ * ------------------------------------------------------------
+ * |             | |B| |A|       | |   |1|0|E|W|A|            |
+ * | BASE 31..24 |G|/|0|V| LIMIT |P|DPL|  TYPE   | BASE 23:16 |
+ * |             | |D| |L| 19..16| |   |1|1|C|R|A|            |
+ * ------------------------------------------------------------
+ * |                             |                            |
+ * |        BASE 15..0           |       LIMIT 15..0          |
+ * |                             |                            |
+ * ------------------------------------------------------------
+ *
+ *  Note the ordering of the data items is reversed from the above
+ *  description.
+ */
+
+       .p2align        2       /* force 4-byte alignment */
+gdt:
+       .word   0, 0
+       .byte   0, 0, 0, 0
+
+       /* code segment */
+       .word   0xFFFF, 0
+       .byte   0, 0x9A, 0xCF, 0
+
+       /* data segment */
+       .word   0xFFFF, 0
+       .byte   0, 0x92, 0xCF, 0
+
+       /* 16 bit real mode CS */
+       .word   0xFFFF, 0
+       .byte   0, 0x9E, 0, 0
+
+       /* 16 bit real mode DS */
+       .word   0xFFFF, 0
+       .byte   0, 0x92, 0, 0
+
+
+/* this is the GDT descriptor */
+gdtdesc:
+       .word   0x27                    /* limit */
+       .long   gdt                     /* addr */
diff --git a/kern/loader.c b/kern/loader.c
new file mode 100644 (file)
index 0000000..f7d8ebc
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/loader.h>
+#include <pupa/misc.h>
+#include <pupa/mm.h>
+#include <pupa/err.h>
+
+static pupa_err_t (*pupa_loader_load_module_func) (int argc, char *argv[]);
+static pupa_err_t (*pupa_loader_boot_func) (void);
+static pupa_err_t (*pupa_loader_unload_func) (void);
+
+static int pupa_loader_loaded;
+
+void
+pupa_loader_set (pupa_err_t (*load_module) (int argc, char *argv[]),
+                pupa_err_t (*boot) (void),
+                pupa_err_t (*unload) (void))
+{
+  if (pupa_loader_loaded && pupa_loader_unload_func)
+    if (pupa_loader_unload_func () != PUPA_ERR_NONE)
+      return;
+  
+  pupa_loader_load_module_func = load_module;
+  pupa_loader_boot_func = boot;
+  pupa_loader_unload_func = unload;
+
+  pupa_loader_loaded = 1;
+}
+
+pupa_err_t
+pupa_loader_load_module (int argc, char *argv[])
+{
+  if (! pupa_loader_loaded)
+    return pupa_error (PUPA_ERR_NO_KERNEL, "no loaded kernel");
+
+  if (! pupa_loader_load_module_func)
+    return pupa_error (PUPA_ERR_BAD_OS, "module not supported");
+
+  return pupa_loader_load_module_func (argc, argv);
+}
+
+pupa_err_t
+pupa_loader_boot (void)
+{
+  if (! pupa_loader_loaded)
+    return pupa_error (PUPA_ERR_NO_KERNEL, "no loaded kernel");
+
+  return (pupa_loader_boot_func) ();
+}
+
diff --git a/kern/main.c b/kern/main.c
new file mode 100644 (file)
index 0000000..2862e52
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/kernel.h>
+#include <pupa/misc.h>
+#include <pupa/mm.h>
+#include <pupa/symbol.h>
+#include <pupa/dl.h>
+#include <pupa/term.h>
+#include <pupa/rescue.h>
+
+/* Return the end of the core image.  */
+pupa_addr_t
+pupa_get_end_addr (void)
+{
+  return pupa_total_module_size + pupa_end_addr;
+}
+
+/* Load all modules in core.  */
+static void
+pupa_load_modules (void)
+{
+  struct pupa_module_header *header;
+
+  for (header = (struct pupa_module_header *) pupa_end_addr;
+       header < (struct pupa_module_header *) pupa_get_end_addr ();
+       header = (struct pupa_module_header *) ((char *) header + header->size))
+    {
+      if (! pupa_dl_load_core ((char *) header + header->offset,
+                              (header->size - header->offset)))
+       pupa_fatal ("%s", pupa_errmsg);
+    }
+}
+
+/* Add the region where modules reside into dynamic memory.  */
+static void
+pupa_add_unused_region (void)
+{
+  if (pupa_total_module_size)
+    pupa_mm_init_region ((void *) pupa_end_addr, pupa_total_module_size);
+}
+
+/* The main routine.  */
+void
+pupa_main (void)
+{
+  void (*normal_func) (void);
+  
+  /* First of all, initialize the machine.  */
+  pupa_machine_init ();
+
+  /* Hello.  */
+  pupa_setcolorstate (PUPA_TERM_COLOR_HIGHLIGHT);
+  pupa_printf ("Welcome to PUPA!");
+  pupa_setcolorstate (PUPA_TERM_COLOR_STANDARD);
+  pupa_printf ("\n\n");
+
+  pupa_register_exported_symbols ();
+  pupa_load_modules ();
+  pupa_add_unused_region ();
+
+  /* If the function pupa_enter_normal_mode is present, call it.  */
+  normal_func = pupa_dl_resolve_symbol ("pupa_enter_normal_mode");
+  if (normal_func)
+    (*normal_func) ();
+
+  /* If pupa_enter_normal_mode fails or doesn't exist, enter rescue mode.  */
+  pupa_printf ("Entering into rescue mode...\n");
+  pupa_enter_rescue_mode ();
+}
diff --git a/kern/misc.c b/kern/misc.c
new file mode 100644 (file)
index 0000000..3ddd3aa
--- /dev/null
@@ -0,0 +1,377 @@
+/* misc.c - definitions of misc functions */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 1999,2000,2001,2002  Free Software Foundation, Inc.
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/misc.h>
+#include <pupa/err.h>
+#include <pupa/mm.h>
+#include <stdarg.h>
+#include <pupa/term.h>
+
+void *
+pupa_memcpy (void *dest, const void *src, pupa_size_t n)
+{
+  char *d = (char *) dest;
+  char *s = (char *) src;
+  
+  while (n--)
+    *d++ = *s++;
+  
+  return dest;
+}
+
+int
+pupa_printf (const char *fmt, ...)
+{
+  va_list ap;
+  int ret;
+  
+  va_start (ap, fmt);
+  ret = pupa_vprintf (fmt, ap);
+  va_end (ap);
+
+  return ret;
+}  
+
+int
+pupa_vprintf (const char *fmt, va_list args)
+{
+  return pupa_vsprintf (0, fmt, args);
+}
+
+int
+pupa_memcmp (const void *s1, const void *s2, pupa_size_t n)
+{
+  const char *t1 = s1;
+  const char *t2 = s2;
+  
+  while (n--)
+    {
+      if (*t1 != *t2)
+       return (int) *t1 - (int) *t2;
+
+      t1++;
+      t2++;
+    }
+
+  return 0;
+}
+
+int
+pupa_strcmp (const char *s1, const char *s2)
+{
+  while (*s1 && *s2)
+    {
+      if (*s1 != *s2)
+       return (int) *s1 - (int) *s2;
+      
+      s1++;
+      s2++;
+    }
+
+  return (int) *s1 - (int) *s2;
+}
+
+char *
+pupa_strchr (const char *s, int c)
+{
+  while (*s)
+    {
+      if (*s == c)
+       return (char *) s;
+      s++;
+    }
+
+  return 0;
+}
+
+char *
+pupa_strrchr (const char *s, int c)
+{
+  char *p = 0;
+
+  while (*s)
+    {
+      if (*s == c)
+       p = (char *) s;
+      s++;
+    }
+
+  return p;
+}
+
+int
+pupa_isspace (int c)
+{
+  return (c == '\n' || c == '\r' || c == ' ' || c == '\t');
+}
+
+int
+pupa_isprint (int c)
+{
+  return (c >= ' ' && c <= '~');
+}
+
+int
+pupa_isalpha (int c)
+{
+  return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+}
+
+int
+pupa_tolower (int c)
+{
+  if (c >= 'A' && c <= 'Z')
+    return c - 'A' + 'a';
+
+  return c;
+}
+
+unsigned long
+pupa_strtoul (const char *str, char **end, int base)
+{
+  unsigned long num = 0;
+  int found = 0;
+  
+  /* Skip white spaces.  */
+  while (*str && pupa_isspace (*str))
+    str++;
+  
+  /* Guess the base, if not specified. The prefix `0x' means 16, and
+     the prefix `0' means 8.  */
+  if (str[0] == '0')
+    {
+      if (str[1] == 'x')
+       {
+         if (base == 0 || base == 16)
+           {
+             base = 16;
+             str += 2;
+           }
+       }
+      else if (str[1] >= '0' && str[1] <= '7')
+       base = 8;
+    }
+  
+  if (base == 0)
+    base = 10;
+
+  while (*str)
+    {
+      unsigned long digit;
+
+      digit = pupa_tolower (*str) - '0';
+      if (digit > 9)
+       {
+         digit += '0' - 'a' + 10;
+         if (digit >= (unsigned long) base)
+           break;
+       }
+
+      found = 1;
+      
+      if (num > (~0UL - digit) / base)
+       {
+         pupa_error (PUPA_ERR_OUT_OF_RANGE, "overflow is detected");
+         return 0;
+       }
+
+      num += num * base + digit;
+      str++;
+    }
+
+  if (! found)
+    {
+      pupa_error (PUPA_ERR_BAD_NUMBER, "unrecognized number");
+      return 0;
+    }
+  
+  if (end)
+    *end = (char *) str;
+
+  return num;
+}
+
+char *
+pupa_strdup (const char *s)
+{
+  pupa_size_t len;
+  char *p;
+  
+  len = pupa_strlen (s) + 1;
+  p = (char *) pupa_malloc (len);
+  if (! p)
+    return 0;
+
+  return pupa_memcpy (p, s, len);
+}
+
+void *
+pupa_memset (void *s, int c, pupa_size_t n)
+{
+  unsigned char *p = (unsigned char *) s;
+
+  while (n--)
+    *p++ = (unsigned char) c;
+
+  return s;
+}
+
+pupa_size_t
+pupa_strlen (const char *s)
+{
+  char *p = (char *) s;
+
+  while (*p)
+    p++;
+
+  return p - s;
+}
+
+static inline void
+pupa_reverse (char *str)
+{
+  char *p = str + pupa_strlen (str) - 1;
+
+  while (str < p)
+    {
+      char tmp;
+
+      tmp = *str;
+      *str = *p;
+      *p = tmp;
+      str++;
+      p--;
+    }
+}
+
+char *
+pupa_itoa (char *str, int c, unsigned n)
+{
+  unsigned base = (c == 'x') ? 16 : 10;
+  char *p;
+  
+  if ((int) n < 0 && c == 'd')
+    {
+      n = (unsigned) (-((int) n));
+      *str++ = '-';
+    }
+
+  p = str;
+  do
+    {
+      unsigned d = n % base;
+      *p++ = (d > 9) ? d + 'a' - 10 : d + '0';
+    }
+  while (n /= base);
+  *p = 0;
+
+  pupa_reverse (str);
+  return p;
+}
+
+int
+pupa_vsprintf (char *str, const char *fmt, va_list args)
+{
+  char c;
+  int count = 0;
+  auto void write_char (char c);
+  auto void write_str (const char *s);
+  
+  void write_char (char c)
+    {
+      if (str)
+       *str++ = c;
+      else
+       pupa_putchar (c);
+
+      count++;
+    }
+
+  void write_str (const char *s)
+    {
+      while (*s)
+       write_char (*s++);
+    }
+  
+  while ((c = *fmt++) != 0)
+    {
+      if (c != '%')
+       write_char (c);
+      else
+       {
+         char tmp[16];
+         char *p;
+         int n;
+         
+         c = *fmt++;
+         
+         switch (c)
+           {
+           case 'p':
+             write_str ("0x");
+             c = 'x';
+             /* fall through */
+           case 'x':
+           case 'u':
+           case 'd':
+             n = va_arg (args, int);
+             pupa_itoa (tmp, c, n);
+             write_str (tmp);
+             break;
+
+           case 'c':
+             n = va_arg (args, int);
+             write_char (n);
+             break;
+
+           case 's':
+             p = va_arg (args, char *);
+             if (p)
+               write_str (p);
+             else
+               write_str ("(null)");
+             break;
+
+           default:
+             write_char (c);
+             break;
+           }
+       }
+    }
+
+  if (str)
+    *str = '\0';
+  
+  return count;
+}
+
+int
+pupa_sprintf (char *str, const char *fmt, ...)
+{
+  va_list ap;
+  int ret;
+  
+  va_start (ap, fmt);
+  ret = pupa_vsprintf (str, fmt, ap);
+  va_end (ap);
+
+  return ret;
+}
diff --git a/kern/mm.c b/kern/mm.c
new file mode 100644 (file)
index 0000000..9b888b6
--- /dev/null
+++ b/kern/mm.c
@@ -0,0 +1,352 @@
+/* mm.c - functions for memory manager */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+#include <pupa/mm.h>
+#include <pupa/misc.h>
+#include <pupa/err.h>
+#include <pupa/types.h>
+#include <pupa/disk.h>
+
+/* Magic words.  */
+#define PUPA_MM_FREE_MAGIC     0x2d3c2808
+#define PUPA_MM_ALLOC_MAGIC    0x6db08fa4
+
+typedef struct pupa_mm_header
+{
+  struct pupa_mm_header *next;
+  pupa_size_t size;
+  pupa_size_t magic;
+#if PUPA_CPU_SIZEOF_VOID_P == 4
+  char padding[4];
+#elif PUPA_CPU_SIZEOF_VOID_P == 8
+  char padding[8];
+#else
+# error "unknown word size"
+#endif
+}
+*pupa_mm_header_t;
+
+#if PUPA_CPU_SIZEOF_VOID_P == 4
+# define PUPA_MM_ALIGN_LOG2    4
+#elif PUPA_CPU_SIZEOF_VOID_P == 8
+# define PUPA_MM_ALIGN_LOG2    8
+#endif
+
+#define PUPA_MM_ALIGN  (1 << PUPA_MM_ALIGN_LOG2)
+
+typedef struct pupa_mm_region
+{
+  struct pupa_mm_header *first;
+  struct pupa_mm_region *next;
+  pupa_addr_t addr;
+  pupa_size_t size;
+}
+*pupa_mm_region_t;
+
+\f
+
+static pupa_mm_region_t base;
+
+/* Get a header from the pointer PTR, and set *P and *R to a pointer
+   to the header and a pointer to its region, respectively. PTR must
+   be allocated.  */
+static void
+get_header_from_pointer (void *ptr, pupa_mm_header_t *p, pupa_mm_region_t *r)
+{
+  if ((unsigned) ptr & (PUPA_MM_ALIGN - 1))
+    pupa_fatal ("unaligned pointer %p", ptr);
+
+  for (*r = base; *r; *r = (*r)->next)
+    if ((unsigned) ptr > (*r)->addr
+       && (unsigned) ptr <= (*r)->addr + (*r)->size)
+      break;
+
+  if (! *r)
+    pupa_fatal ("out of range pointer %p", ptr);
+  
+  *p = (pupa_mm_header_t) ptr - 1;
+  if ((*p)->magic != PUPA_MM_ALLOC_MAGIC)
+    pupa_fatal ("alloc magic is broken at %p", *p);
+}
+
+/* Initialize a region starting from ADDR and whose size is SIZE,
+   to use it as free space.  */
+void
+pupa_mm_init_region (void *addr, pupa_size_t size)
+{
+  pupa_mm_header_t h;
+  pupa_mm_region_t r, *p, q;
+
+  /* If this region is too small, ignore it.  */
+  if (size < PUPA_MM_ALIGN * 2)
+    return;
+
+  /* Allocate a region from the head.  */
+  r = (pupa_mm_region_t) (((pupa_addr_t) addr + PUPA_MM_ALIGN - 1)
+                         & (~(PUPA_MM_ALIGN - 1)));
+  size -= (char *) r - (char *) addr + sizeof (*r);
+  
+  h = (pupa_mm_header_t) ((char *) r + PUPA_MM_ALIGN);
+  h->next = h;
+  h->magic = PUPA_MM_FREE_MAGIC;
+  h->size = (size >> PUPA_MM_ALIGN_LOG2);
+
+  r->first = h;
+  r->addr = (pupa_addr_t) h;
+  r->size = (h->size << PUPA_MM_ALIGN_LOG2);
+
+  /* Find where to insert this region. Put a smaller one before bigger ones,
+     to prevent fragmentations.  */
+  for (p = &base, q = *p; q; p = &(q->next), q = *p)
+    if (q->size > r->size)
+      break;
+  
+  *p = r;
+  r->next = q;
+}
+
+/* Allocate the number of units N with the alignment ALIGN from the ring
+   buffer starting from *FIRST. ALIGN must be a power of two. Return a
+   non-NULL if successful, otherwise return NULL.  */
+static void *
+pupa_real_malloc (pupa_mm_header_t *first, pupa_size_t n, pupa_size_t align)
+{
+  pupa_mm_header_t p, q;
+  
+  if ((*first)->magic == PUPA_MM_ALLOC_MAGIC)
+    return 0;
+
+  for (q = *first, p = q->next; ; q = p, p = p->next)
+    {
+      pupa_off_t extra;
+
+      extra = ((pupa_addr_t) (p + 1) >> PUPA_MM_ALIGN_LOG2) % align;
+      if (extra)
+       extra = align - extra;
+
+      if (! p)
+       pupa_fatal ("null in the ring");
+
+      if (p->magic != PUPA_MM_FREE_MAGIC)
+       pupa_fatal ("free magic is broken at %p", p);
+
+      if (p->size >= n + extra)
+       {
+         if (extra == 0 && p->size == n)
+           {
+             q->next = p->next;
+             p->magic = PUPA_MM_ALLOC_MAGIC;
+           }
+         else if (extra == 0 || p->size == n + extra)
+           {
+             p->size -= n;
+             p += p->size;
+             p->size = n;
+             p->magic = PUPA_MM_ALLOC_MAGIC;
+           }
+         else
+           {
+             pupa_mm_header_t r;
+
+             r = p + extra + n;
+             r->magic = PUPA_MM_FREE_MAGIC;
+             r->size = p->size - extra - n;
+             r->next = p->next;
+             
+             p->size = extra;
+             p->next = r;
+             p += extra;
+             p->size = n;
+             p->magic = PUPA_MM_ALLOC_MAGIC;
+           }
+
+         *first = q;
+         return p + 1;
+       }
+
+      if (p == *first)
+       break;
+    }
+
+  return 0;
+}
+
+/* Allocate SIZE bytes with the alignment ALIGN and return the pointer.  */
+void *
+pupa_memalign (pupa_size_t align, pupa_size_t size)
+{
+  pupa_mm_region_t r;
+  pupa_size_t n = ((size + PUPA_MM_ALIGN - 1) >> PUPA_MM_ALIGN_LOG2) + 1;
+  int first = 1;
+  
+  align = (align >> PUPA_MM_ALIGN_LOG2);
+  if (align == 0)
+    align = 1;
+
+ again:
+  
+  for (r = base; r; r = r->next)
+    {
+      void *p;
+      
+      p = pupa_real_malloc (&(r->first), n, align);
+      if (p)
+       return p;
+    }
+
+  /* If failed, invalidate disk caches to increase free memory.  */
+  if (first)
+    {
+      pupa_disk_cache_invalidate_all ();
+      first = 0;
+      goto again;
+    }
+
+  pupa_error (PUPA_ERR_OUT_OF_MEMORY, "out of memory");
+  return 0;
+}
+
+/* Allocate SIZE bytes and return the pointer.  */
+void *
+pupa_malloc (pupa_size_t size)
+{
+  return pupa_memalign (0, size);
+}
+
+/* Deallocate the pointer PTR.  */
+void
+pupa_free (void *ptr)
+{
+  pupa_mm_header_t p;
+  pupa_mm_region_t r;
+
+  if (! ptr)
+    return;
+
+  get_header_from_pointer (ptr, &p, &r);
+
+  if (p == r->first)
+    {
+      p->magic = PUPA_MM_FREE_MAGIC;
+      p->next = p;
+    }
+  else
+    {
+      pupa_mm_header_t q;
+      
+      for (q = r->first; q >= p || q->next <= p; q = q->next)
+       {
+         if (q->magic != PUPA_MM_FREE_MAGIC)
+           pupa_fatal ("free magic is broken at %p", q);
+         
+         if (q >= q->next && (q < p || q->next > p))
+           break;
+       }
+
+      p->magic = PUPA_MM_FREE_MAGIC;
+      p->next = q->next;
+      q->next = p;
+      
+      if (p + p->size == p->next)
+       {
+         p->next->magic = 0;
+         p->size += p->next->size;
+         p->next = p->next->next;
+       }
+      
+      if (q + q->size == p)
+       {
+         p->magic = 0;
+         q->size += p->size;
+         q->next = p->next;
+       }
+
+      r->first = q;
+    }
+}
+
+/* Reallocate SIZE bytes and return the pointer. The contents will be
+   the same as that of PTR.  */
+void *
+pupa_realloc (void *ptr, pupa_size_t size)
+{
+  pupa_mm_header_t p;
+  pupa_mm_region_t r;
+  void *q;
+  pupa_size_t n;
+  
+  if (! ptr)
+    return pupa_malloc (size);
+
+  if (! size)
+    {
+      pupa_free (ptr);
+      return 0;
+    }
+
+  /* FIXME: Not optimal.  */
+  n = ((size + PUPA_MM_ALIGN - 1) >> PUPA_MM_ALIGN_LOG2) + 1;
+  get_header_from_pointer (ptr, &p, &r);
+  
+  if (p->size >= n)
+    return p;
+  
+  q = pupa_malloc (size);
+  if (! q)
+    return q;
+  
+  pupa_memcpy (q, ptr, size);
+  pupa_free (ptr);
+  return q;
+}
+
+#if MM_DEBUG
+void
+pupa_mm_dump (unsigned lineno)
+{
+  pupa_mm_region_t r;
+
+  pupa_printf ("called at line %u\n", lineno);
+  for (r = base; r; r = r->next)
+    {
+      pupa_mm_header_t p;
+      
+      for (p = (pupa_mm_header_t) ((r->addr + PUPA_MM_ALIGN - 1)
+                                  & (~(PUPA_MM_ALIGN - 1)));
+          (pupa_addr_t) p < r->addr + r->size;
+          p++)
+       {
+         switch (p->magic)
+           {
+           case PUPA_MM_FREE_MAGIC:
+             pupa_printf ("F:%p:%u:%p\n",
+                          p, p->size << PUPA_MM_ALIGN_LOG2, p->next);
+             break;
+           case PUPA_MM_ALLOC_MAGIC:
+             pupa_printf ("A:%p:%u\n", p, p->size << PUPA_MM_ALIGN_LOG2);
+             break;
+           }
+       }
+    }
+
+  pupa_printf ("\n");
+}
+#endif /* MM_DEBUG */
diff --git a/kern/rescue.c b/kern/rescue.c
new file mode 100644 (file)
index 0000000..29aecb8
--- /dev/null
@@ -0,0 +1,576 @@
+/* rescue.c - rescue mode */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/kernel.h>
+#include <pupa/term.h>
+#include <pupa/misc.h>
+#include <pupa/disk.h>
+#include <pupa/file.h>
+#include <pupa/mm.h>
+#include <pupa/err.h>
+#include <pupa/loader.h>
+#include <pupa/machine/partition.h>
+
+#define PUPA_RESCUE_BUF_SIZE   256
+#define PUPA_RESCUE_MAX_ARGS   20
+
+struct pupa_rescue_command
+{
+  const char *name;
+  void (*func) (int argc, char *argv[]);
+  const char *message;
+  struct pupa_rescue_command *next;
+};
+typedef struct pupa_rescue_command *pupa_rescue_command_t;
+
+static char buf[PUPA_RESCUE_BUF_SIZE];
+
+static pupa_rescue_command_t pupa_rescue_command_list;
+
+void
+pupa_rescue_register_command (const char *name,
+                             void (*func) (int argc, char *argv[]),
+                             const char *message)
+{
+  pupa_rescue_command_t cmd;
+
+  cmd = (pupa_rescue_command_t) pupa_malloc (sizeof (*cmd));
+  if (! cmd)
+    return;
+
+  cmd->name = name;
+  cmd->func = func;
+  cmd->message = message;
+
+  cmd->next = pupa_rescue_command_list;
+  pupa_rescue_command_list = cmd;
+}
+
+void
+pupa_rescue_unregister_command (const char *name)
+{
+  pupa_rescue_command_t *p, q;
+
+  for (p = &pupa_rescue_command_list, q = *p; q; p = &(q->next), q = q->next)
+    if (pupa_strcmp (name, q->name) == 0)
+      {
+       *p = q->next;
+       pupa_free (q);
+       break;
+      }
+}
+
+/* Prompt to input a command and read the line.  */
+static void
+pupa_rescue_get_command_line (const char *prompt)
+{
+  int c;
+  int pos = 0;
+  
+  pupa_printf (prompt);
+  pupa_memset (buf, 0, PUPA_RESCUE_BUF_SIZE);
+  
+  while ((c = PUPA_TERM_ASCII_CHAR (pupa_getkey ())) != '\n' && c != '\r')
+    {
+      if (pupa_isprint (c))
+       {
+         if (pos < PUPA_RESCUE_BUF_SIZE - 1)
+           {
+             buf[pos++] = c;
+             pupa_putchar (c);
+           }
+       }
+      else if (c == '\b')
+       {
+         if (pos > 0)
+           {
+             buf[--pos] = 0;
+             pupa_putchar (c);
+             pupa_putchar (' ');
+             pupa_putchar (c);
+           }
+       }
+    }
+
+  pupa_putchar ('\n');
+}
+
+/* Get the next word in STR and return a next pointer.  */
+static char *
+next_word (char **str)
+{
+  char *word;
+  char *p = *str;
+  
+  /* Skip spaces.  */
+  while (*p && pupa_isspace (*p))
+    p++;
+
+  word = p;
+
+  /* Find a space.  */
+  while (*p && ! pupa_isspace (*p))
+    p++;
+
+  *p = '\0';
+  *str = p + 1;
+  
+  return word;
+}
+
+/* boot */
+static void
+pupa_rescue_cmd_boot (int argc __attribute__ ((unused)),
+                     char *argv[] __attribute__ ((unused)))
+{
+  pupa_loader_boot ();
+}
+
+/* cat FILE */
+static void
+pupa_rescue_cmd_cat (int argc, char *argv[])
+{
+  pupa_file_t file;
+  char buf[PUPA_DISK_SECTOR_SIZE];
+  pupa_ssize_t size;
+
+  if (argc < 1)
+    {
+      pupa_error (PUPA_ERR_BAD_ARGUMENT, "no file specified");
+      return;
+    }
+  
+  file = pupa_file_open (argv[0]);
+  if (! file)
+    return;
+
+  while ((size = pupa_file_read (file, buf, sizeof (buf))) > 0)
+    {
+      int i;
+
+      for (i = 0; i < size; i++)
+       {
+         unsigned char c = buf[i];
+
+         if (pupa_isprint (c) || pupa_isspace (c))
+           pupa_putchar (c);
+         else
+           {
+             pupa_setcolorstate (PUPA_TERM_COLOR_HIGHLIGHT);
+             pupa_printf ("<%x>", (int) c);
+             pupa_setcolorstate (PUPA_TERM_COLOR_STANDARD);
+           }
+       }
+    }
+
+  pupa_putchar ('\n');
+  pupa_file_close (file);
+}
+
+static int
+pupa_rescue_print_disks (const char *name)
+{
+  pupa_device_t dev;
+  auto int print_partition (const pupa_partition_t p);
+
+  int print_partition (const pupa_partition_t p)
+    {
+      char *pname = pupa_partition_get_name (p);
+
+      if (pname)
+       {
+         pupa_printf ("(%s,%s) ", name, pname);
+         pupa_free (pname);
+       }
+
+      return 0;
+    }
+
+  dev = pupa_device_open (name);
+  pupa_errno = PUPA_ERR_NONE;
+  
+  if (dev)
+    {
+      pupa_printf ("(%s) ", name);
+
+      if (dev->disk && dev->disk->has_partitions)
+       {
+         pupa_partition_iterate (dev->disk, print_partition);
+         pupa_errno = PUPA_ERR_NONE;
+       }
+
+      pupa_device_close (dev);
+    }
+  
+  return 0;
+}
+
+static int
+pupa_rescue_print_files (const char *filename, int dir)
+{
+  pupa_printf ("%s%s ", filename, dir ? "/" : "");
+  
+  return 0;
+}
+
+/* ls [ARG] */
+static void
+pupa_rescue_cmd_ls (int argc, char *argv[])
+{
+  if (argc < 1)
+    {
+      pupa_disk_dev_iterate (pupa_rescue_print_disks);
+      pupa_putchar ('\n');
+    }
+  else
+    {
+      char *device_name;
+      pupa_device_t dev;
+      pupa_fs_t fs;
+      char *path;
+      
+      device_name = pupa_file_get_device_name (argv[0]);
+      dev = pupa_device_open (device_name);
+      if (! dev)
+       goto fail;
+
+      fs = pupa_fs_probe (dev);
+      path = pupa_strchr (argv[0], '/');
+
+      if (! path && ! device_name)
+       {
+         pupa_error (PUPA_ERR_BAD_ARGUMENT, "invalid argument");
+         goto fail;
+       }
+      
+      if (! path)
+       {
+         if (pupa_errno == PUPA_ERR_UNKNOWN_FS)
+           pupa_errno = PUPA_ERR_NONE;
+         
+         pupa_printf ("(%s): Filesystem is %s.\n",
+                      device_name, fs ? fs->name : "unknown");
+       }
+      else if (fs)
+       {
+         (fs->dir) (dev, path, pupa_rescue_print_files);
+         pupa_putchar ('\n');
+       }
+
+    fail:
+      if (dev)
+       pupa_device_close (dev);
+      
+      pupa_free (device_name);
+    }
+}
+
+/* help */
+static void
+pupa_rescue_cmd_help (int argc __attribute__ ((unused)),
+                     char *argv[] __attribute__ ((unused)))
+{
+  pupa_rescue_command_t p, q;
+
+  /* Sort the commands. This is not a good algorithm, but this is enough,
+     because rescue mode has a small number of commands.  */
+  for (p = pupa_rescue_command_list; p; p = p->next)
+    for (q = p->next; q; q = q->next)
+      if (pupa_strcmp (p->name, q->name) > 0)
+       {
+         struct pupa_rescue_command tmp;
+
+         tmp.name = p->name;
+         tmp.func = p->func;
+         tmp.message = p->message;
+
+         p->name = q->name;
+         p->func = q->func;
+         p->message = q->message;
+
+         q->name = tmp.name;
+         q->func = tmp.func;
+         q->message = tmp.message;
+       }
+
+  /* Print them.  */
+  for (p = pupa_rescue_command_list; p; p = p->next)
+    pupa_printf ("%s\t%s\n", p->name, p->message);
+}
+
+#if 0
+static void
+pupa_rescue_cmd_info (void)
+{
+  extern void pupa_disk_cache_get_performance (unsigned long *,
+                                              unsigned long *);
+  unsigned long hits, misses;
+  
+  pupa_disk_cache_get_performance (&hits, &misses);
+  pupa_printf ("Disk cache: hits = %u, misses = %u ", hits, misses);
+  if (hits + misses)
+    {
+      unsigned long ratio = hits * 10000 / (hits + misses);
+      pupa_printf ("(%u.%u%%)\n", ratio / 100, ratio % 100);
+    }
+  else
+    pupa_printf ("(N/A)\n");
+}
+#endif
+
+/* (module|initrd) FILE [ARGS] */
+static void
+pupa_rescue_cmd_module (int argc, char *argv[])
+{
+  pupa_loader_load_module (argc, argv);
+}
+
+/* root [DEVICE] */
+static void
+pupa_rescue_cmd_root (int argc, char *argv[])
+{
+  pupa_device_t dev;
+  pupa_fs_t fs;
+
+  if (argc > 0)
+    {
+      char *device_name = pupa_file_get_device_name (argv[0]);
+      if (! device_name)
+       return;
+      
+      pupa_device_set_root (device_name);
+      pupa_free (device_name);
+    }
+  
+  dev = pupa_device_open (0);
+  if (! dev)
+    return;
+
+  fs = pupa_fs_probe (dev);
+  if (pupa_errno == PUPA_ERR_UNKNOWN_FS)
+    pupa_errno = PUPA_ERR_NONE;
+  
+  pupa_printf ("(%s): Filesystem is %s.\n",
+              pupa_device_get_root (), fs ? fs->name : "unknown");
+  
+  pupa_device_close (dev);
+}
+
+#if 0
+static void
+pupa_rescue_cmd_testload (int argc, char *argv[])
+{
+  pupa_file_t file;
+  char *buf;
+  pupa_ssize_t size;
+  pupa_ssize_t pos;
+  auto void read_func (unsigned long sector, unsigned offset, unsigned len);
+
+  void read_func (unsigned long sector __attribute__ ((unused)),
+                 unsigned offset __attribute__ ((unused)),
+                 unsigned len __attribute__ ((unused)))
+    {
+      pupa_putchar ('.');
+    }
+
+  if (argc < 1)
+    {
+      pupa_error (PUPA_ERR_BAD_ARGUMENT, "no file specified");
+      return;
+    }
+  
+  file = pupa_file_open (argv[0]);
+  if (! file)
+    return;
+
+  size = pupa_file_size (file) & ~(PUPA_DISK_SECTOR_SIZE - 1);
+  if (size == 0)
+    {
+      pupa_file_close (file);
+      return;
+    }
+  
+  buf = pupa_malloc (size);
+  if (! buf)
+    goto fail;
+
+  pupa_printf ("Reading %s sequentially", argv[0]);
+  file->read_hook = read_func;
+  if (pupa_file_read (file, buf, size) != size)
+    goto fail;
+  pupa_printf (" Done.\n");
+
+  /* Read sequentially again.  */
+  pupa_printf ("Reading %s sequentially again", argv[0]);
+  if (pupa_file_seek (file, 0) < 0)
+    goto fail;
+  
+  for (pos = 0; pos < size; pos += PUPA_DISK_SECTOR_SIZE)
+    {
+      char sector[PUPA_DISK_SECTOR_SIZE];
+      
+      if (pupa_file_read (file, sector, PUPA_DISK_SECTOR_SIZE)
+         != PUPA_DISK_SECTOR_SIZE)
+       goto fail;
+
+      if (pupa_memcmp (sector, buf + pos, PUPA_DISK_SECTOR_SIZE) != 0)
+       {
+         pupa_printf ("\nDiffers in %d\n", pos);
+         goto fail;
+       }
+    }
+  pupa_printf (" Done.\n");
+  
+  /* Read backwards and compare.  */
+  pupa_printf ("Reading %s backwards", argv[0]);
+  pos = size;
+  while (pos > 0)
+    {
+      char sector[PUPA_DISK_SECTOR_SIZE];
+      
+      pos -= PUPA_DISK_SECTOR_SIZE;
+      
+      if (pupa_file_seek (file, pos) < 0)
+       goto fail;
+      
+      if (pupa_file_read (file, sector, PUPA_DISK_SECTOR_SIZE)
+         != PUPA_DISK_SECTOR_SIZE)
+       goto fail;
+
+      if (pupa_memcmp (sector, buf + pos, PUPA_DISK_SECTOR_SIZE) != 0)
+       {
+         int i;
+         
+         pupa_printf ("\nDiffers in %d\n", pos);
+         
+         for (i = 0; i < PUPA_DISK_SECTOR_SIZE; i++)
+           pupa_putchar (buf[pos + i]);
+         
+         goto fail;
+       }
+    }
+  pupa_printf (" Done.\n");
+
+ fail:
+
+  pupa_file_close (file);
+  pupa_free (buf);
+}
+#endif
+
+static void
+pupa_rescue_cmd_dump (int argc, char *argv[])
+{
+  pupa_uint8_t *addr;
+  pupa_size_t size = 4;
+  
+  if (argc == 0)
+    {
+      pupa_error (PUPA_ERR_BAD_ARGUMENT, "no address specified");
+      return;
+    }
+
+  addr = (pupa_uint8_t *) pupa_strtoul (argv[0], 0, 0);
+  if (pupa_errno)
+    return;
+
+  if (argc > 1)
+    size = (pupa_size_t) pupa_strtoul (argv[1], 0, 0);
+
+  while (size--)
+    {
+      pupa_printf ("%x%x ", *addr >> 4, *addr & 0xf);
+      addr++;
+    }
+}
+
+/* Enter the rescue mode.  */
+void
+pupa_enter_rescue_mode (void)
+{
+  pupa_rescue_register_command ("boot", pupa_rescue_cmd_boot,
+                               "boot an operating system");
+  pupa_rescue_register_command ("cat", pupa_rescue_cmd_cat,
+                               "show the contents of a file");
+  pupa_rescue_register_command ("help", pupa_rescue_cmd_help,
+                               "show this message");
+  pupa_rescue_register_command ("initrd", pupa_rescue_cmd_module,
+                               "load an initrd");
+  pupa_rescue_register_command ("ls", pupa_rescue_cmd_ls,
+                               "list devices or files");
+  pupa_rescue_register_command ("module", pupa_rescue_cmd_module,
+                               "load an OS module");
+  pupa_rescue_register_command ("root", pupa_rescue_cmd_root,
+                               "set a root device");
+  pupa_rescue_register_command ("dump", pupa_rescue_cmd_dump,
+                               "dump memory");
+  
+  while (1)
+    {
+      char *line = buf;
+      char *name;
+      int n;
+      pupa_rescue_command_t cmd;
+      char *args[PUPA_RESCUE_MAX_ARGS + 1];
+
+      /* Get a command line.  */
+      pupa_rescue_get_command_line ("pupa rescue> ");
+
+      /* Get the command name.  */
+      name = next_word (&line);
+
+      /* If nothing is specified, restart.  */
+      if (*name == '\0')
+       continue;
+
+      /* Get arguments.  */
+      for (n = 0; n <= PUPA_RESCUE_MAX_ARGS; n++)
+       {
+         char *arg = next_word (&line);
+         
+         if (*arg)
+           args[n] = arg;
+         else
+           break;
+       }
+      args[n] = 0;
+
+      /* Find the command and execute it.  */
+      for (cmd = pupa_rescue_command_list; cmd; cmd = cmd->next)
+       {
+         if (pupa_strcmp (name, cmd->name) == 0)
+           {
+             (cmd->func) (n, args);
+             break;
+           }
+       }
+      
+      /* If not found, print an error message.  */
+      if (! cmd)
+       {
+         pupa_printf ("Unknown command `%s'\n", name);
+         pupa_printf ("Try `help' for usage\n");
+       }
+      
+      /* Print an error, if any.  */
+      pupa_print_error ();
+      pupa_errno = PUPA_ERR_NONE;
+    }
+}
diff --git a/kern/term.c b/kern/term.c
new file mode 100644 (file)
index 0000000..509e5c8
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Free Software Foundation, Inc.
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/term.h>
+#include <pupa/err.h>
+#include <pupa/mm.h>
+
+/* The list of terminals.  */
+static pupa_term_t pupa_term_list;
+
+/* The current terminal.  */
+static pupa_term_t pupa_cur_term;
+
+void
+pupa_term_register (pupa_term_t term)
+{
+  term->next = pupa_term_list;
+  pupa_term_list = term;
+}
+
+void
+pupa_term_unregister (pupa_term_t term)
+{
+  pupa_term_t *p, q;
+  
+  for (p = &pupa_term_list, q = *p; q; p = &(q->next), q = q->next)
+    if (q == term)
+      {
+        *p = q->next;
+       break;
+      }
+}
+
+void
+pupa_term_iterate (int (*hook) (pupa_term_t term))
+{
+  pupa_term_t p;
+  
+  for (p = pupa_term_list; p; p = p->next)
+    if (hook (p))
+      break;
+}
+
+void
+pupa_term_set_current (pupa_term_t term)
+{
+  pupa_cur_term = term;
+}
+
+pupa_term_t
+pupa_term_get_current (void)
+{
+  return pupa_cur_term;
+}
+
+void
+pupa_putchar (int c)
+{
+  if (c == '\n')
+    pupa_putchar ('\r');
+  else if (c == '\t' && pupa_cur_term->getxy)
+    {
+      int n;
+
+      n = 8 - ((pupa_getxy () >> 8) & 7);
+      while (n--)
+       pupa_putchar (' ');
+
+      return;
+    }
+  
+  (pupa_cur_term->putchar) (c);
+}
+
+int
+pupa_getkey (void)
+{
+  return (pupa_cur_term->getkey) ();
+}
+
+int
+pupa_checkkey (void)
+{
+  return (pupa_cur_term->checkkey) ();
+}
+
+pupa_uint16_t
+pupa_getxy (void)
+{
+  return (pupa_cur_term->getxy) ();
+}
+
+void
+pupa_gotoxy (pupa_uint8_t x, pupa_uint8_t y)
+{
+  (pupa_cur_term->gotoxy) (x, y);
+}
+
+void
+pupa_cls (void)
+{
+  if (pupa_cur_term->flags & PUPA_TERM_DUMB)
+    pupa_putchar ('\n');
+  else
+    (pupa_cur_term->cls) ();
+}
+
+void
+pupa_setcolorstate (pupa_term_color_state state)
+{
+  if (pupa_cur_term->setcolorstate)
+    (pupa_cur_term->setcolorstate) (state);
+}
+
+void
+pupa_setcolor (pupa_uint8_t normal_color, pupa_uint8_t highlight_color)
+{
+  if (pupa_cur_term->setcolor)
+    (pupa_cur_term->setcolor) (normal_color, highlight_color);
+}
+
+int
+pupa_setcursor (int on)
+{
+  static int prev = 1;
+  int ret = prev;
+
+  if (pupa_cur_term->setcursor)
+    {
+      (pupa_cur_term->setcursor) (on);
+      prev = on;
+    }
+  
+  return ret;
+}
+
diff --git a/loader/i386/pc/chainloader.c b/loader/i386/pc/chainloader.c
new file mode 100644 (file)
index 0000000..911f795
--- /dev/null
@@ -0,0 +1,137 @@
+/* chainloader.c - boot another boot loader */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/loader.h>
+#include <pupa/machine/loader.h>
+#include <pupa/file.h>
+#include <pupa/err.h>
+#include <pupa/device.h>
+#include <pupa/disk.h>
+#include <pupa/misc.h>
+#include <pupa/types.h>
+#include <pupa/machine/init.h>
+#include <pupa/machine/partition.h>
+#include <pupa/machine/memory.h>
+#include <pupa/rescue.h>
+#include <pupa/dl.h>
+
+/* Allocate space statically, because this is very small anyway.  */
+static char pupa_chainloader_boot_sector[PUPA_DISK_SECTOR_SIZE];
+
+static pupa_err_t
+pupa_chainloader_boot (void)
+{
+  pupa_device_t dev;
+  int drive = -1;
+  void *part_addr = 0;
+  
+  /* Open the root device.  */
+  dev = pupa_device_open (0);
+  if (dev)
+    {
+      pupa_disk_t disk = dev->disk;
+      
+      if (disk)
+       {
+         pupa_partition_t p = disk->partition;
+         
+         /* In i386-pc, the id is equal to the BIOS drive number.  */
+         drive = (int) disk->id;
+
+         if (p)
+           {
+             pupa_disk_read (disk, p->offset, 446, 64,
+                             (char *) PUPA_MEMORY_MACHINE_PART_TABLE_ADDR);
+             
+             /* Ignore errors. Perhaps it's not fatal.  */
+             part_addr = (void *) (PUPA_MEMORY_MACHINE_PART_TABLE_ADDR
+                                   + (p->index << 4));
+           }
+       }
+
+      pupa_device_close (dev);
+    }
+
+  pupa_chainloader_real_boot (drive, part_addr);
+
+  /* Never reach here.  */
+  return PUPA_ERR_NONE;
+}
+
+static void
+pupa_rescue_cmd_chainloader (int argc, char *argv[])
+{
+  pupa_file_t file;
+  pupa_uint16_t signature;
+  int force = 0;
+
+  if (argc > 0 && pupa_strcmp (argv[0], "--force") == 0)
+    {
+      force = 1;
+      argc--;
+      argv++;
+    }
+
+  if (argc == 0)
+    {
+      pupa_error (PUPA_ERR_BAD_ARGUMENT, "no file specified");
+      return;
+    }
+
+  file = pupa_file_open (argv[0]);
+  if (! file)
+    return;
+
+  /* Read the first block.  */
+  if (pupa_file_read (file, pupa_chainloader_boot_sector,
+                     PUPA_DISK_SECTOR_SIZE) != PUPA_DISK_SECTOR_SIZE)
+    {
+      if (pupa_errno == PUPA_ERR_NONE)
+       pupa_error (PUPA_ERR_BAD_OS, "too small");
+
+      pupa_file_close (file);
+      return;
+    }
+
+  /* Check the signature.  */
+  signature = *((pupa_uint16_t *) (pupa_chainloader_boot_sector
+                                  + PUPA_DISK_SECTOR_SIZE - 2));
+  if (signature != pupa_le_to_cpu16 (0xaa55) && ! force)
+    pupa_error (PUPA_ERR_BAD_OS, "invalid signature");
+
+  pupa_file_close (file);
+
+  if (pupa_errno == PUPA_ERR_NONE)
+    pupa_loader_set (0, pupa_chainloader_boot, 0);
+}
+
+static const char loader_name[] = "chainloader";
+
+PUPA_MOD_INIT
+{
+  pupa_rescue_register_command (loader_name,
+                               pupa_rescue_cmd_chainloader,
+                               "load another boot loader");
+}
+
+PUPA_MOD_FINI
+{
+  pupa_rescue_unregister_command (loader_name);
+}
diff --git a/mkinstalldirs b/mkinstalldirs
new file mode 100644 (file)
index 0000000..6b3b5fc
--- /dev/null
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id$
+
+errstatus=0
+
+for file
+do
+   set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+   shift
+
+   pathcomp=
+   for d
+   do
+     pathcomp="$pathcomp$d"
+     case "$pathcomp" in
+       -* ) pathcomp=./$pathcomp ;;
+     esac
+
+     if test ! -d "$pathcomp"; then
+        echo "mkdir $pathcomp"
+
+        mkdir "$pathcomp" || lasterr=$?
+
+        if test ! -d "$pathcomp"; then
+         errstatus=$lasterr
+        fi
+     fi
+
+     pathcomp="$pathcomp/"
+   done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/stamp-h.in b/stamp-h.in
new file mode 100644 (file)
index 0000000..9788f70
--- /dev/null
@@ -0,0 +1 @@
+timestamp
diff --git a/term/i386/pc/console.c b/term/i386/pc/console.c
new file mode 100644 (file)
index 0000000..b0a3b88
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002  Free Software Foundation, Inc.
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <pupa/machine/console.h>
+#include <pupa/term.h>
+#include <pupa/types.h>
+
+pupa_uint8_t pupa_console_cur_color = 0x7;
+static pupa_uint8_t pupa_console_standard_color = 0x7;
+static pupa_uint8_t pupa_console_normal_color = 0x7;
+static pupa_uint8_t pupa_console_highlight_color = 0x70;
+
+static void
+pupa_console_setcolorstate (pupa_term_color_state state)
+{
+  switch (state) {
+    case PUPA_TERM_COLOR_STANDARD:
+      pupa_console_cur_color = pupa_console_standard_color;
+      break;
+    case PUPA_TERM_COLOR_NORMAL:
+      pupa_console_cur_color = pupa_console_normal_color;
+      break;
+    case PUPA_TERM_COLOR_HIGHLIGHT:
+      pupa_console_cur_color = pupa_console_highlight_color;
+      break;
+    default:
+      break;
+  }
+}
+
+static void
+pupa_console_setcolor (pupa_uint8_t normal_color, pupa_uint8_t highlight_color)
+{
+  pupa_console_normal_color = normal_color;
+  pupa_console_highlight_color = highlight_color;
+}
+
+static struct pupa_term pupa_console_term =
+  {
+    .name = "console",
+    .putchar = pupa_console_putchar,
+    .checkkey = pupa_console_checkkey,
+    .getkey = pupa_console_getkey,
+    .getxy = pupa_console_getxy,
+    .gotoxy = pupa_console_gotoxy,
+    .cls = pupa_console_cls,
+    .setcolorstate = pupa_console_setcolorstate,
+    .setcolor = pupa_console_setcolor,
+    .setcursor = pupa_console_setcursor,
+    .flags = 0,
+    .next = 0
+  };
+
+void
+pupa_console_init (void)
+{
+  pupa_term_register (&pupa_console_term);
+  pupa_term_set_current (&pupa_console_term);
+}
diff --git a/util/genmoddep.c b/util/genmoddep.c
new file mode 100644 (file)
index 0000000..20da7a5
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002  Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#define BUF_SIZE       1024
+#define SYMTAB_SIZE    509
+
+struct symbol
+{
+  const char *name;
+  const char *mod;
+  struct symbol *next;
+};
+
+struct module
+{
+  const char *name;
+  struct module *next;
+};
+
+static char buf[BUF_SIZE];
+static struct symbol *symtab[SYMTAB_SIZE];
+
+static void
+err (const char *fmt, ...)
+{
+  va_list ap;
+
+  fprintf (stderr, "genmoddep: error: ");
+  
+  va_start (ap, fmt);
+  vfprintf (stderr, fmt, ap);
+  va_end (ap);
+
+  fputc ('\n', stderr);
+  exit (1);
+}
+
+static void *
+xmalloc (size_t size)
+{
+  void *p;
+
+  p = malloc (size);
+  if (! p)
+    err ("out of memory");
+
+  return p;
+}
+
+static char *
+xstrdup (const char *str)
+{
+  char *s;
+  size_t len;
+
+  len = strlen (str);
+  s = (char *) xmalloc (len + 1);
+  memcpy (s, str, len + 1);
+
+  return s;
+}
+
+static void
+chomp (char *str)
+{
+  int end;
+  
+  end = strlen (str) - 1;
+  if (end < 0)
+    err ("empty string");
+
+  if (str[end] == '\n')
+    str[end] = '\0';
+}
+
+static unsigned
+symbol_hash (const char *s)
+{
+  unsigned key = 0;
+
+  while (*s)
+    key = key * 65599 + *s++;
+
+  return (key + (key >> 5)) % SYMTAB_SIZE;
+}
+
+static struct symbol *
+get_symbol (const char *name)
+{
+  unsigned k;
+  struct symbol *sym;
+  
+  k = symbol_hash (name);
+  for (sym = symtab[k]; sym; sym = sym->next)
+    if (strcmp (sym->name, name) == 0)
+      return sym;
+
+  return 0;
+}
+
+static void
+add_symbol (const char *name, const char *mod)
+{
+  unsigned k;
+  struct symbol *sym;
+
+  if (get_symbol (name))
+    err ("duplicated symbol: %s", name);
+  
+  sym = (struct symbol *) xmalloc (sizeof (*sym));
+  sym->name = xstrdup (name);
+  sym->mod = xstrdup (mod);
+
+  k = symbol_hash (name);
+  sym->next = symtab[k];
+  symtab[k] = sym;
+}
+
+static void
+free_symbols (void)
+{
+  int i;
+
+  for (i = 0; i < SYMTAB_SIZE; i++)
+    {
+      struct symbol *p, *q;
+
+      p = symtab[i];
+      while (p)
+       {
+         q = p->next;
+         free ((void *) p->name);
+         free ((void *) p->mod);
+         free (p);
+         p = q;
+       }
+    }
+}
+
+static void
+read_defined_symbols (FILE *fp)
+{
+  while (fgets (buf, sizeof (buf), fp))
+    {
+      char *p;
+
+      if (! *buf)
+       err ("empty symbol name: %s", buf);
+      
+      p = strchr (buf, ' ');
+      if (! p)
+       err ("invalid line format: %s", buf);
+
+      p++;
+      
+      if (! *p)
+       err ("empty module name: %s", buf);
+
+      *(p - 1) = '\0';
+      chomp (p);
+      
+      add_symbol (buf, p);
+    }
+}
+
+static void
+add_module (struct module **head, const char *name)
+{
+  struct module *mod;
+
+  for (mod = *head; mod; mod = mod->next)
+    if (strcmp (mod->name, name) == 0)
+      return;
+
+  mod = (struct module *) xmalloc (sizeof (*mod));
+  mod->name = xstrdup (name);
+
+  mod->next = *head;
+  *head = mod;
+}
+
+static void
+free_modules (struct module *head)
+{
+  struct module *next;
+
+  while (head)
+    {
+      next = head->next;
+      free ((void *) head->name);
+      free (head);
+      head = next;
+    }
+}
+
+static void
+find_dependencies (FILE *fp)
+{
+  char *mod_name;
+  struct module *mod_list = 0;
+  struct module *mod;
+  
+  if (! fgets (buf, sizeof (buf), fp) || buf[0] == '\n' || buf[0] == '\0')
+    err ("no module name");
+
+  chomp (buf);
+  mod_name = xstrdup (buf);
+
+  while (fgets (buf, sizeof (buf), fp))
+    {
+      struct symbol *sym;
+      
+      chomp (buf);
+      sym = get_symbol (buf);
+      if (! sym)
+       err ("%s in %s is not defined", buf, mod_name);
+
+      add_module (&mod_list, sym->mod);
+    }
+
+  printf ("%s:", mod_name);
+  
+  for (mod = mod_list; mod; mod = mod->next)
+    if (strcmp (mod->name, "kernel") != 0)
+      printf (" %s", mod->name);
+  
+  putchar ('\n');
+
+  free_modules (mod_list);
+}
+
+int
+main (int argc, char *argv[])
+{
+  int i;
+  
+  /* First, get defined symbols.  */
+  read_defined_symbols (stdin);
+
+  /* Second, find the dependecies.  */
+  for (i = 1; i < argc; i++)
+    {
+      FILE *fp;
+
+      fp = fopen (argv[i], "r");
+      if (! fp)
+       err ("cannot open %s", argv[i]);
+
+      find_dependencies (fp);
+
+      fclose (fp);
+    }
+
+  /* Last, free memory.  */
+  free_symbols ();
+  
+  return 0;
+}
diff --git a/util/i386/pc/grub-mkimage.c b/util/i386/pc/grub-mkimage.c
new file mode 100644 (file)
index 0000000..68a28c5
--- /dev/null
@@ -0,0 +1,223 @@
+/* pupa-mkimage.c - make a bootable image */
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+#include <pupa/types.h>
+#include <pupa/machine/boot.h>
+#include <pupa/machine/kernel.h>
+#include <pupa/kernel.h>
+#include <pupa/disk.h>
+#include <pupa/util/misc.h>
+#include <pupa/util/resolve.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define _GNU_SOURCE    1
+#include <getopt.h>
+
+static void
+generate_image (const char *dir, FILE *out, char *mods[])
+{
+  pupa_addr_t module_addr = 0;
+  char *kernel_img, *boot_img;
+  size_t kernel_size, boot_size, total_module_size;
+  char *kernel_path, *boot_path;
+  unsigned num;
+  struct pupa_util_path_list *path_list, *p, *next;
+
+  path_list = pupa_util_resolve_dependencies (dir, "moddep.lst", mods);
+
+  kernel_path = pupa_util_get_path (dir, "kernel.img");
+  kernel_size = pupa_util_get_image_size (kernel_path);
+
+  total_module_size = 0;
+  for (p = path_list; p; p = p->next)
+    total_module_size += (pupa_util_get_image_size (p->name)
+                         + sizeof (struct pupa_module_header));
+
+  pupa_util_info ("the total module size is 0x%x", total_module_size);
+  
+  num = ((kernel_size + total_module_size + PUPA_DISK_SECTOR_SIZE - 1)
+        >> PUPA_DISK_SECTOR_BITS);
+  if (num > 0xffff)
+    pupa_util_error ("the core image is too big");
+
+  boot_path = pupa_util_get_path (dir, "diskboot.img");
+  boot_size = pupa_util_get_image_size (boot_path);
+  if (boot_size != PUPA_DISK_SECTOR_SIZE)
+    pupa_util_error ("diskboot.img is not one sector size");
+  
+  boot_img = pupa_util_read_image (boot_path);
+  
+  /* i386 is a little endian architecture.  */
+  *((pupa_uint16_t *) (boot_img + PUPA_DISK_SECTOR_SIZE
+                      - PUPA_BOOT_MACHINE_LIST_SIZE + 4))
+    = pupa_cpu_to_le16 (num);
+
+  pupa_util_write_image (boot_img, boot_size, out);
+  free (boot_img);
+  free (boot_path);
+  
+  kernel_img = pupa_util_read_image (kernel_path);
+  module_addr = (path_list
+                ? (PUPA_BOOT_MACHINE_KERNEL_ADDR + PUPA_DISK_SECTOR_SIZE
+                   + kernel_size)
+                : 0);
+
+  pupa_util_info ("the first module address is 0x%x", module_addr);
+  *((pupa_uint32_t *) (kernel_img + PUPA_KERNEL_MACHINE_TOTAL_MODULE_SIZE))
+    = pupa_cpu_to_le32 (total_module_size);
+  *((pupa_uint32_t *) (kernel_img + PUPA_KERNEL_MACHINE_KERNEL_IMAGE_SIZE))
+    = pupa_cpu_to_le32 (kernel_size);
+  
+  pupa_util_write_image (kernel_img, kernel_size, out);
+  free (kernel_img);
+  free (kernel_path);
+
+  while (path_list)
+    {
+      struct pupa_module_header header;
+      size_t mod_size;
+      char *mod_img;
+      
+      next = path_list->next;
+      
+      mod_size = pupa_util_get_image_size (path_list->name);
+
+      header.offset = pupa_cpu_to_le32 (sizeof (header));
+      header.size = pupa_cpu_to_le32 (mod_size + sizeof (header));
+
+      pupa_util_info ("offset=0x%x, size=0x%x", header.offset, header.size);
+      pupa_util_write_image ((char *) &header, sizeof (header), out);
+      
+      mod_img = pupa_util_read_image (path_list->name);
+      pupa_util_write_image (mod_img, mod_size, out);
+      free (mod_img);
+
+      free ((void *) path_list->name);
+      free (path_list);
+      path_list = next;
+    }
+}
+
+\f
+
+static struct option options[] =
+  {
+    {"directory", required_argument, 0, 'd'},
+    {"output", required_argument, 0, 'o'},
+    {"help", no_argument, 0, 'h'},
+    {"version", no_argument, 0, 'V'},
+    {"verbose", no_argument, 0, 'v'},
+    {0, 0, 0, 0}
+  };
+
+static void
+usage (int status)
+{
+  if (status)
+    fprintf (stderr, "Try ``pupa-mkimage --help'' for more information.\n");
+  else
+    printf ("\
+Usage: pupa-mkimage [OPTION]... [MODULES]\n\
+\n\
+Make a bootable image of PUPA.\n\
+\n\
+  -d, --directory=DIR     use images and modules under DIR [default=%s]\n\
+  -o, --output=FILE       output a generated image to FILE [default=stdout]\n\
+  -h, --help              display this image and exit\n\
+  -V, --version           print version information and exit\n\
+  -v, --verbose           print verbose messages\n\
+\n\
+Report bugs to <okuji@enbug.org>.\n\
+", PUPA_DATADIR);
+
+  exit (status);
+}
+
+int
+main (int argc, char *argv[])
+{
+  char *output = 0;
+  char *dir = 0;
+  FILE *fp = stdout;
+
+  progname = "pupa-mkimage";
+  
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "d:o:hVv", options, 0);
+
+      if (c == -1)
+       break;
+      else
+       switch (c)
+         {
+         case 'o':
+           if (output)
+             free (output);
+           
+           output = xstrdup (optarg);
+           break;
+
+         case 'd':
+           if (dir)
+             free (dir);
+
+           dir = xstrdup (optarg);
+           break;
+
+         case 'h':
+           usage (0);
+           break;
+
+         case 'V':
+           printf ("pupa-mkimage (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+           return 0;
+
+         case 'v':
+           verbosity++;
+           break;
+
+         default:
+           usage (1);
+           break;
+         }
+    }
+
+  if (output)
+    {
+      fp = fopen (output, "wb");
+      if (! fp)
+       pupa_util_error ("cannot open %s", output);
+    }
+
+  generate_image (dir ? : PUPA_DATADIR, fp, argv + optind);
+
+  fclose (fp);
+
+  if (dir)
+    free (dir);
+
+  return 0;
+}
diff --git a/util/misc.c b/util/misc.c
new file mode 100644 (file)
index 0000000..6f65eb1
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <pupa/util/misc.h>
+
+char *progname = 0;
+int verbosity = 0;
+
+void
+pupa_util_info (const char *fmt, ...)
+{
+  if (verbosity > 0)
+    {
+      va_list ap;
+      
+      fprintf (stderr, "%s: info: ", progname);
+      va_start (ap, fmt);
+      vfprintf (stderr, fmt, ap);
+      va_end (ap);
+      fputc ('\n', stderr);
+    }
+}
+
+void
+pupa_util_error (const char *fmt, ...)
+{
+  va_list ap;
+  
+  fprintf (stderr, "%s: error: ", progname);
+  va_start (ap, fmt);
+  vfprintf (stderr, fmt, ap);
+  va_end (ap);
+  fputc ('\n', stderr);
+  exit (1);
+}
+
+void *
+xmalloc (size_t size)
+{
+  void *p;
+  
+  p = malloc (size);
+  if (! p)
+    pupa_util_error ("out of memory");
+
+  return p;
+}
+
+char *
+xstrdup (const char *str)
+{
+  size_t len;
+  char *dup;
+  
+  len = strlen (str);
+  dup = (char *) xmalloc (len + 1);
+  memcpy (dup, str, len + 1);
+
+  return dup;
+}
+
+char *
+pupa_util_get_path (const char *dir, const char *file)
+{
+  char *path;
+  
+  path = (char *) xmalloc (strlen (dir) + 1 + strlen (file) + 1);
+  sprintf (path, "%s/%s", dir, file);
+  return path;
+}
+
+size_t
+pupa_util_get_image_size (const char *path)
+{
+  struct stat st;
+  
+  pupa_util_info ("getting the size of %s", path);
+  
+  if (stat (path, &st) == -1)
+    pupa_util_error ("cannot stat %s", path);
+  
+  return st.st_size;
+}
+
+char *
+pupa_util_read_image (const char *path)
+{
+  char *img;
+  FILE *fp;
+  size_t size;
+  
+  pupa_util_info ("reading %s", path);
+
+  size = pupa_util_get_image_size (path);
+  img = (char *) xmalloc (size);
+
+  fp = fopen (path, "rb");
+  if (! fp)
+    pupa_util_error ("cannot open %s", path);
+  
+  if (fread (img, 1, size, fp) != size)
+    pupa_util_error ("cannot read %s", path);
+
+  return img;
+}
+
+void
+pupa_util_write_image (const char *img, size_t size, FILE *out)
+{
+  pupa_util_info ("writing 0x%x bytes", size);
+  if (fwrite (img, 1, size, out) != size)
+    pupa_util_error ("write failed");
+}
+
diff --git a/util/resolve.c b/util/resolve.c
new file mode 100644 (file)
index 0000000..8f98569
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ *  PUPA  --  Preliminary Universal Programming Architecture for GRUB
+ *  Copyright (C) 2002 Yoshinori K. Okuji <okuji@enbug.org>
+ *
+ *  PUPA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with PUPA; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <pupa/util/resolve.h>
+#include <pupa/util/misc.h>
+
+/* Module.  */
+struct mod_list
+{
+  const char *name;
+  struct mod_list *next;
+};
+
+/* Dependency.  */
+struct dep_list
+{
+  const char *name;
+  struct mod_list *list;
+  struct dep_list *next;
+};
+
+static char buf[1024];
+
+static void
+free_mod_list (struct mod_list *head)
+{
+  while (head)
+    {
+      struct mod_list *next;
+
+      next = head->next;
+      free ((void *) head->name);
+      free (head);
+      head = next;
+    }
+}
+
+static void
+free_dep_list (struct dep_list *head)
+{
+  while (head)
+    {
+      struct dep_list *next;
+
+      next = head->next;
+      free ((void *) head->name);
+      free_mod_list (head->list);
+      free (head);
+      head = next;
+    }
+}
+
+/* Read the list of dependencies.  */
+static struct dep_list *
+read_dep_list (FILE *fp)
+{
+  struct dep_list *dep_list = 0;
+  
+  while (fgets (buf, sizeof (buf), fp))
+    {
+      char *p;
+      struct dep_list *dep;
+
+      /* Get the target name.  */
+      p = strchr (buf, ':');
+      if (! p)
+       pupa_util_error ("invalid line format: %s", buf);
+
+      *p++ = '\0';
+
+      dep = xmalloc (sizeof (*dep));
+      dep->name = xstrdup (buf);
+      dep->list = 0;
+      
+      dep->next = dep_list;
+      dep_list = dep;
+
+      /* Add dependencies.  */
+      while (*p)
+       {
+         struct mod_list *mod;
+         char *name;
+
+         /* Skip white spaces.  */
+         while (*p && isspace (*p))
+           p++;
+
+         if (! *p)
+           break;
+
+         name = p;
+
+         /* Skip non-WSPs.  */
+         while (*p && ! isspace (*p))
+           p++;
+
+         *p++ = '\0';
+         
+         mod = (struct mod_list *) xmalloc (sizeof (*mod));
+         mod->name = xstrdup (name);
+         mod->next = dep->list;
+         dep->list = mod;
+       }
+    }
+
+  return dep_list;
+}
+
+static char *
+get_module_name (const char *str)
+{
+  char *base;
+  char *ext;
+  
+  base = strrchr (str, '/');
+  if (! base)
+    base = (char *) str;
+  else
+    base++;
+
+  ext = strrchr (base, '.');
+  if (ext && strcmp (ext, ".mod") == 0)
+    {
+      char *name;
+      
+      name = xmalloc (ext - base + 1);
+      memcpy (name, base, ext - base);
+      name[ext - base] = '\0';
+      return name;
+    }
+  
+  return xstrdup (base);
+}
+
+static char *
+get_module_path (const char *prefix, const char *str)
+{
+  char *dir;
+  char *base;
+  char *ext;
+  char *ret;
+  
+  ext = strrchr (str, '.');
+  if (ext && strcmp (ext, ".mod") == 0)
+    base = xstrdup (str);
+  else
+    {
+      base = xmalloc (strlen (str) + 4 + 1);
+      sprintf (base, "%s.mod", str);
+    }
+  
+  dir = strchr (str, '/');
+  if (dir)
+    return base;
+
+  ret = pupa_util_get_path (prefix, base);
+  free (base);
+  return ret;
+}
+
+static void
+add_module (const char *dir,
+           struct dep_list *dep_list,
+           struct mod_list **mod_head,
+           struct pupa_util_path_list **path_head,
+           const char *name)
+{
+  char *mod_name;
+  struct pupa_util_path_list *path;
+  struct mod_list *mod;
+  struct dep_list *dep;
+  
+  mod_name = get_module_name (name);
+
+  /* Check if the module has already been added.  */
+  for (mod = *mod_head; mod; mod = mod->next)
+    if (strcmp (mod->name, mod_name) == 0)
+      {
+       free (mod_name);
+       return;
+      }
+
+  /* Resolve dependencies.  */
+  for (dep = dep_list; dep; dep = dep->next)
+    if (strcmp (dep->name, mod_name) == 0)
+      {
+       for (mod = dep->list; mod; mod = mod->next)
+         add_module (dir, dep_list, mod_head, path_head, mod->name);
+
+       break;
+      }
+
+  /* Add this module.  */
+  mod = (struct mod_list *) xmalloc (sizeof (*mod));
+  mod->name = mod_name;
+  mod->next = *mod_head;
+  *mod_head = mod;
+
+  /* Add this path.  */
+  path = (struct pupa_util_path_list *) xmalloc (sizeof (*path));
+  path->name = get_module_path (dir, name);
+  path->next = *path_head;
+  *path_head = path;
+}
+
+struct pupa_util_path_list *
+pupa_util_resolve_dependencies (const char *prefix,
+                               const char *dep_list_file,
+                               char *modules[])
+{
+  char *path;
+  FILE *fp;
+  struct dep_list *dep_list;
+  struct mod_list *mod_list = 0;
+  struct pupa_util_path_list *path_list = 0;
+  
+  path = pupa_util_get_path (prefix, dep_list_file);
+  fp = fopen (path, "r");
+  if (! fp)
+    pupa_util_error ("cannot open %s", path);
+
+  free (path);
+  dep_list = read_dep_list (fp);
+  fclose (fp);
+
+  while (*modules)
+    {
+      add_module (prefix, dep_list, &mod_list, &path_list, *modules);
+      modules++;
+    }
+
+  free_dep_list (dep_list);
+  free_mod_list (mod_list);
+
+  return path_list;
+}